默认 http.defaultclient 会复用连接,但需服务端支持 keep-alive;手动创建 client 未配置 transport 时,其 maxidleconns 和 maxidleconnsperhost 默认为 0,导致不复用连接。

Go net/http 默认客户端不复用连接?
默认的 http.DefaultClient 确实会复用连接,但前提是服务端支持 HTTP/1.1 keep-alive 且没主动关闭。问题常出在你手动构造了新 http.Client 却没配 Transport,导致每次请求都新建 TCP 连接、不回收。
- 漏设
Transport是最常见原因:没给http.Client指定Transport,它会用默认值;但若你写了&http.Client{}又没显式传Transport,Go 会初始化一个全新http.Transport实例——而它的MaxIdleConns和MaxIdleConnsPerHost默认都是 0(即禁用空闲连接池) - 服务端返回
Connection: close时,即使客户端配了池,这次连接也不会被复用 -
http.Transport的IdleConnTimeout默认是 30 秒,超时后连接会被关掉;如果业务 RT 长或突发流量后连接闲置久,池里连接数可能骤降,触发重建潮
如何安全配置 http.Transport 防泄漏
关键不是“调大数字”,而是让连接生命周期和业务节奏匹配,同时防止失控增长。
-
MaxIdleConns设为 0 表示不限制总空闲连接数(不推荐);生产建议设为 100–500,具体看后端实例数和单机 QPS -
MaxIdleConnsPerHost必须设,否则默认 0 → 所有主机共享 0 个空闲连接 → 全部新建连接。建议设为MaxIdleConns / 后端域名数,比如 200 / 2 = 100 -
IdleConnTimeout建议 30–90 秒;太短会导致频繁建连,太长会在低峰期占着 FD 不放 -
ResponseHeaderTimeout和ExpectContinueTimeout要设,否则慢响应或卡在 100-continue 阶段会一直占着连接 - 别忘了
CloseIdleConnections()—— 在服务优雅退出前调用,否则进程退出时连接可能残留数秒
示例:
tr := &http.Transport{
MaxIdleConns: 200,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 60 * time.Second,
ResponseHeaderTimeout: 5 * time.Second,
}
client := &http.Client{Transport: tr}
HTTP/2 对连接复用的影响
Go 1.6+ 默认启用 HTTP/2,但它对连接复用的逻辑和 HTTP/1.1 不同:一个 TCP 连接可承载多个并发 stream,所以 MaxIdleConnsPerHost 的意义变弱了——只要 TCP 连接没断,stream 就能复用它。
- HTTP/2 下更需关注
MaxConnsPerHost(控制最大 TCP 连接数),默认 0(无限制),高吞吐下建议设为 5–10 - 服务端若只支持 HTTP/1.1,客户端强制启 HTTP/2 会降级失败;用
http.Transport.ForceAttemptHTTP2要谨慎 - HTTP/2 的连接空闲超时由
IdleConnTimeout控制,但 stream 级超时由ResponseHeaderTimeout和RoundTrip上下文控制,两者要协同
怎么确认连接真泄露了?
别只盯着 netstat -an | grep :80 | wc -l,那只是瞬时快照。真正要盯的是连接状态分布和增长趋势。
立即学习“go语言免费学习笔记(深入)”;
- 查
/proc/<pid>/fd/</pid>下 socket 数量:持续上涨且不回落,大概率泄漏 - 用
go tool pprof http://localhost:6060/debug/pprof/goroutine?debug=1看是否有大量net/http.(*persistConn).readLoop或writeLoopgoroutine 卡住 - 开启
http.Transport的Trace字段,记录连接获取/释放日志,定位哪次请求没释放 - 注意:
http.Client本身不泄漏,泄漏源永远是Transport+ 使用方式 —— 比如忘记resp.Body.Close(),会导致底层连接无法归还到池中
最后提醒一句:所有 http.Response.Body 必须显式 Close(),哪怕你只读前几个字节。这是最隐蔽、最高发的连接滞留点。










