使用http2实现时可能出现的竞争情况

时间:2019-01-30 18:23:39

标签: http go mutex race-condition

我有一个奇怪的问题,在生产中很少发生。

我有一个不错的http客户端可以重用连接。

DefaultClient = &http.Client{
    Transport: &http.Transport{
        Proxy: http.ProxyFromEnvironment,
        DialContext: (&net.Dialer{
            Timeout:   500 * time.Millisecond,
            KeepAlive: 1 * time.Minute,
        }).DialContext,
        TLSHandshakeTimeout: 500 * time.Millisecond,
        MaxIdleConns:        3000,
        MaxIdleConnsPerHost: 3000,
        IdleConnTimeout:     1 * time.Minute,
    },
    Timeout: 500 * time.Millisecond,
}

每一次,由于无法从紧急状态中恢复,机器将变得无响应,这似乎与Go标准http lib中的互斥锁锁定和解锁有关。

goroutine 47888935 [semacquire, 7 minutes]:
sync.runtime_SemacquireMutex(0xc00040126c, 0x0)
    /usr/local/go/src/runtime/sema.go:71 +0x3d
sync.(*Mutex).Lock(0xc000401268)
    /usr/local/go/src/sync/mutex.go:134 +0xff
net/http.(*http2clientConnPool).getClientConn(0xc000401260, 0xc028295f00, 0xc0281de820, 0x12, 0xc00027a400, 0xc0283266a8, 0x6aafa0, 0xc00027a410)
    /usr/local/go/src/net/http/h2_bundle.go:760 +0x65
net/http.http2noDialClientConnPool.GetClientConn(0xc000401260, 0xc028295f00, 0xc0281de820, 0x12, 0xc0281de820, 0x12, 0x0)
    /usr/local/go/src/net/http/h2_bundle.go:954 +0x4e
net/http.(*http2Transport).RoundTripOpt(0xc00027a410, 0xc028295f00, 0x0, 0x200000000000000, 0x4137ec, 0xb940aa)
    /usr/local/go/src/net/http/h2_bundle.go:7031 +0x105
net/http.(*http2Transport).RoundTrip(0xc00027a410, 0xc028295f00, 0x1, 0xc028307800, 0x0)
    /usr/local/go/src/net/http/h2_bundle.go:6999 +0x3a
net/http.http2noDialH2RoundTripper.RoundTrip(0xc00027a410, 0xc028295f00, 0xc0282cf800, 0x5, 0xc00059c2c8)
    /usr/local/go/src/net/http/h2_bundle.go:1019 +0x39
net/http.(*Transport).roundTrip(0xc000177680, 0xc028295f00, 0xc028267a70, 0xc02801ff88, 0xc02801ff90)
    /usr/local/go/src/net/http/transport.go:415 +0xd4c
net/http.(*Transport).RoundTrip(0xc000177680, 0xc028295f00, 0xc000177680, 0xbf0c9388b63791ca, 0x2122772ff0fc)
    /usr/local/go/src/net/http/roundtrip.go:17 +0x35
net/http.send(0xc028295e00, 0xc99600, 0xc000177680, 0xbf0c9388b63791ca, 0x2122772ff0fc, 0x11d03a0, 0xc027ef3480, 0xbf0c9388b63791ca, 0xc028326cb8, 0x1)
    /usr/local/go/src/net/http/client.go:250 +0x14b
net/http.(*Client).send(0xc000400360, 0xc028295e00, 0xbf0c9388b63791ca, 0x2122772ff0fc, 0x11d03a0, 0xc027ef3480, 0x0, 0x1, 0xc000518000)
    /usr/local/go/src/net/http/client.go:174 +0xfa
net/http.(*Client).do(0xc000400360, 0xc028295e00, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/http/client.go:641 +0x2a8
net/http.(*Client).Do(0xc000400360, 0xc028295e00, 0x10, 0xb933f5, 0x4)
    /usr/local/go/src/net/http/client.go:509 +0x35

这种情况很少发生在高流量,高产量的产品中,因此很难复制。

是否有人曾经经历过此事或对可能的问题有任何见解?似乎与http客户端紧密相关。

0 个答案:

没有答案