http - go 程序在执行数小时后系统地在 semacquire 问题上崩溃
问题描述
这是我的代码的摘录:
func sendTo(url string, someDataPoints [] DataPoint) {
ro := &grequests.RequestOptions{JSON: someDataPoints, InsecureSkipVerify: false}
grequests.Post(url, ro)
return
}
func forward(someDataPoints []DataPoint) int {
endpoint := "https://example.org"
go sendTo(endpoint, someDataPoints)
}
函数 forward 被称为每秒 100 次。该程序运行了三十个小时左右,最终失败并出现以下错误:
goroutine 265125012 [semacquire, 41 minutes]:
sync.runtime_notifyListWait(0xc4204be2d0, 0x1bb56b6)
/usr/local/go/src/runtime/sema.go:510 +0x10b
sync.(*Cond).Wait(0xc4204be2c0)
/usr/local/go/src/sync/cond.go:56 +0x80
net/http.(*http2ClientConn).awaitOpenSlotForRequest(0xc420d5e000, 0xc42c167000, 0x0, 0x0)
/usr/local/go/src/net/http/h2_bundle.go:7528 +0x11d
net/http.(*http2ClientConn).roundTrip(0xc420d5e000, 0xc42c167000, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/net/http/h2_bundle.go:7336 +0x110
net/http.(*http2Transport).RoundTripOpt(0xc4200100f0, 0xc42c167000, 0xffffffffffffff00, 0x0, 0x40bac0, 0x705e50)
/usr/local/go/src/net/http/h2_bundle.go:6929 +0x150
net/http.(*http2Transport).RoundTrip(0xc4200100f0, 0xc42c167000, 0xc42c1a04c0, 0x0, 0xc42c1a0438)
/usr/local/go/src/net/http/h2_bundle.go:6891 +0x3a
net/http.http2noDialH2RoundTripper.RoundTrip(0xc4200100f0, 0xc42c167000, 0x7fff668abf02, 0x5, 0xc42016a088)
/usr/local/go/src/net/http/h2_bundle.go:991 +0x39
net/http.(*Transport).RoundTrip(0x8aa800, 0xc42c167000, 0x8aa800, 0x0, 0x0)
/usr/local/go/src/net/http/transport.go:380 +0xc36
net/http.send(0xc42c167000, 0x745660, 0x8aa800, 0x0, 0x0, 0x0, 0xc44002b628, 0xb000000000411729, 0xc420d52b50, 0x1)
/usr/local/go/src/net/http/client.go:252 +0x185
net/http.(*Client).send(0x8afa20, 0xc42c167000, 0x0, 0x0, 0x0, 0xc44002b628, 0x0, 0x1, 0x698620)
/usr/local/go/src/net/http/client.go:176 +0xfa
net/http.(*Client).Do(0x8afa20, 0xc42c167000, 0x7fff668abf02, 0x3a, 0xc42bcc5b80)
/usr/local/go/src/net/http/client.go:615 +0x28d
github.com/levigross/grequests.buildRequest(0x705a0f, 0x4, 0x7fff668abf02, 0x3a, 0xc42bcc5b80, 0x8afa20, 0x8, 0x18, 0xc431e455a0)
/go/src/github.com/levigross/grequests/request.go:194 +0x189
github.com/levigross/grequests.doRegularRequest(0x705a0f, 0x4, 0x7fff668abf02, 0x3a, 0xc42bcc5b80, 0x690380, 0x1, 0xc431e455a0)
/go/src/github.com/levigross/grequests/request.go:136 +0x6f
github.com/levigross/grequests.Post(0x7fff668abf02, 0x3a, 0xc42bcc5b80, 0xc431e455a0, 0x4, 0xc42c1703c0)
/go/src/github.com/levigross/grequests/base.go:41 +0x54
main.sendTo(0x7fff668abf02, 0x3a, 0xc42bcd33b0, 0x1, 0x1, 0x0, 0x0)
/go/src/github.com/SomeCompany/SomeProduct/cmd/SomeCli/main.go:66 +0xdd
created by main.forward
/go/src/github.com/SomeCompany/SomeProduct/cmd/SomeCli/main.go:80 +0xc8
什么可以解释这个问题?
解决方案
那里似乎没有显示实际错误。只是一个堆栈跟踪。我不确定为什么。
我所看到的是,您似乎只是无限制地启动 goroutine。如果您的程序无法sendTo
以比到达更快的速度转发和完成请求,您的程序会怎么做?
我认为在某些时候 Go 会耗尽 goroutine 堆栈的内存,或者其他东西会溢出。我预计会出现某种“内存不足”错误,但我在那里没有看到。
尽管如此,这是我最好的猜测:由于创建的 goroutine 比完成的多,导致某种资源耗尽。
推荐阅读
- regex - java.util.regex.PatternSyntaxException:字符串 +91 的悬挂元字符“+”
- java - 如何使用过滤器来处理 servlet 中抛出的异常
- javascript - 我想创建自己的标签,例如
, - ms-access - Microsoft Access - 登录
- audio - 带有音频和视频过滤器的 ffplay / ffmpeg
- java - 在java中添加三个不同的char作为java变量并获取一个数字
- android - 通过终端命令在Android上打开振动
- javascript - 删除 VuetifyJS v-tabs 组件的标头
- webpack - 如何将 TheIntern 与 Webpack 和 Babel 一起使用
- c++ - CMake子项目不能调用OpenGL函数,但父项目可以