首页 > 解决方案 > 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

什么可以解释这个问题?

标签: httpgo

解决方案


那里似乎没有显示实际错误。只是一个堆栈跟踪。我不确定为什么。

我所看到的是,您似乎只是无限制地启动 goroutine。如果您的程序无法sendTo以比到达更快的速度转发和完成请求,您的程序会怎么做?

我认为在某些时候 Go 会耗尽 goroutine 堆栈的内存,或者其他东西会溢出。我预计会出现某种“内存不足”错误,但我在那里没有看到。

尽管如此,这是我最好的猜测:由于创建的 goroutine 比完成的多,导致某种资源耗尽。


推荐阅读