调用io.ReadAll读取HTTP响应体时出现goroutine泄漏问题求助
解决HTTP请求后goroutine泄漏问题
你遇到的goroutine泄漏是因为Go标准库的http.Client默认启用了HTTP/2传输,HTTP/2连接会启动后台goroutine(比如http2ClientConn的readLoop)来持续读取连接上的帧数据。这些goroutine在连接处于空闲状态时不会立即退出,测试结束时goleak就会把它们判定为意外goroutine。
下面是三种可行的解决办法:
方法1:禁用HTTP/2,强制使用HTTP/1.1
通过修改http.Transport的TLSNextProto字段为空map,让客户端只使用HTTP/1.1,这样就不会启动HTTP/2相关的后台goroutine:
func TestLeak(t *testing.T) { defer goleak.VerifyNone(t) request, err := http.NewRequest(http.MethodGet, "https://google.com", nil) assert.NilError(t, err) // 自定义Transport禁用HTTP/2 client := http.Client{ Transport: &http.Transport{ TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper), }, } response, err := client.Do(request) assert.NilError(t, err) defer response.Body.Close() _, err = io.ReadAll(response.Body) assert.NilError(t, err) }
方法2:显式关闭Transport的空闲连接
如果你需要保留HTTP/2,可以自己创建独立的http.Transport实例,在测试结束前调用CloseIdleConnections()主动关闭所有空闲连接,触发相关goroutine退出:
func TestLeak(t *testing.T) { defer goleak.VerifyNone(t) request, err := http.NewRequest(http.MethodGet, "https://google.com", nil) assert.NilError(t, err) // 创建独立Transport,测试结束关闭空闲连接 transport := &http.Transport{} defer transport.CloseIdleConnections() client := http.Client{Transport: transport} response, err := client.Do(request) assert.NilError(t, err) defer response.Body.Close() _, err = io.ReadAll(response.Body) assert.NilError(t, err) }
方法3:让goleak忽略HTTP/2相关goroutine
如果必须保留HTTP/2且不想主动关闭连接,可以配置goleak忽略那些HTTP/2后台goroutine的栈顶函数:
func TestLeak(t *testing.T) { // 忽略http2ClientConn的readLoop goroutine defer goleak.VerifyNone(t, goleak.IgnoreTopFunction("net/http.(*http2ClientConn).readLoop")) request, err := http.NewRequest(http.MethodGet, "https://google.com", nil) assert.NilError(t, err) client := http.Client{} response, err := client.Do(request) assert.NilError(t, err) defer response.Body.Close() _, err = io.ReadAll(response.Body) assert.NilError(t, err) }
各方法适用场景
- 方法1:适合不需要HTTP/2特性的场景,简单直接。
- 方法2:适合需要HTTP/2且希望严格清理资源的测试场景。
- 方法3:适合必须保留HTTP/2连接复用的场景,仅在测试中忽略预期的goroutine。
内容的提问来源于stack exchange,提问作者wxh
相关产品推荐
相关产品推荐

