go的http.client默认启用keep-alive,无需手动开启,但需确保服务端支持、调用resp.body.close()、合理配置transport参数(如maxidleconnsperhost和idleconntimeout)并避免设置connection: close。

Keep-Alive 在 Go 的 net/http 中默认就开启
Go 的 http.Client 默认复用 TCP 连接,只要服务端也支持,Connection: keep-alive 就会自动生效。你不需要手动设置请求头,也不用显式启用开关——它不是“功能”,而是 Go HTTP 客户端的底层行为。
真正影响 Keep-Alive 是否实际起效的,是连接池配置和请求/响应生命周期管理:
-
http.DefaultClient使用http.DefaultTransport,其MaxIdleConns和MaxIdleConnsPerHost默认都是 100,足够应对多数场景 - 如果服务端返回
Connection: close,或响应体未被完整读取(比如resp.Body.Close()没调用、或提前break出循环),连接会被强制关闭,无法复用 - 超时参数(如
IdleConnTimeout)控制空闲连接存活时间,默认 30 秒;太短会导致频繁重建连接
如何确认 Keep-Alive 正在工作
最直接的方式是观察 TCP 连接数变化,而不是看请求头。Go 不暴露连接复用细节,但你可以通过 http.Transport 的指标间接验证:
- 启用
Transport.IdleConnTimeout并设为较长值(如60 * time.Second),避免连接过早释放 - 在多次请求后检查
Transport.IdleConnStats()(需自定义 Transport),或用lsof -i :<port></port>/netstat观察客户端 ESTABLISHED 连接数是否稳定 - 抓包看 TCP 层:连续请求间没有
SYN,只有ACK + data,说明连接复用成功
注意:不要依赖 req.Header.Set("Connection", "keep-alive")——Go 会忽略它,甚至在某些版本中覆盖为你设的值。
常见导致 Keep-Alive 失效的操作
即使 Transport 配置合理,下面这些代码习惯会让连接无法复用:
- 忘记调用
resp.Body.Close():这是最常见原因。未关闭 Body,Transport 认为响应未结束,不会把连接放回空闲池 - 使用
io.Copy(ioutil.Discard, resp.Body)但没关 Body:同样,Copy 不等于 Close - 对同一个
http.Client实例并发发请求,但MaxIdleConnsPerHost设得太小(如 1),高并发下连接池耗尽,新请求被迫新建连接 - 服务端主动发送
Connection: close或使用 HTTP/1.0 协议(无 Keep-Alive 语义)
一个安全写法示例:
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close() // 必须放在这里,哪怕后续有 error 检查
body, err := io.ReadAll(resp.Body) // 确保读完
if err != nil {
return err
}
// ... 处理 body
需要精细控制时怎么配 Transport
如果你压测或对接不稳定的后端,建议显式构造 http.Transport,而非依赖默认值:
-
MaxIdleConns控制全局最大空闲连接数,设为 0 表示不限(不推荐) -
MaxIdleConnsPerHost更关键,建议按后端域名设(如 20~100),避免单个 host 占满池子 -
IdleConnTimeout建议 30–90 秒;太长可能占着连接却不被复用,太短增加握手开销 - 如果后端支持 HTTP/2,不用额外配置 Keep-Alive——HTTP/2 默认多路复用,连接复用更彻底
示例配置片段:
transport := &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 50,
IdleConnTimeout: 60 * time.Second,
}
client := &http.Client{Transport: transport}
真正容易被忽略的是:Keep-Alive 的效果高度依赖服务端配合与客户端资源清理习惯,而不是某一行开关代码。连不上、复用不了,先查 Body.Close() 和响应状态码,再看 Transport 配置。











