必须配置maxidleconns、maxidleconnsperhost和idleconntimeout三个参数,否则高并发下连接池失效导致频繁建连或连接泄漏;需确保resp.body.close()被显式调用,否则连接无法归还池中;http/2需tls且证书有效才能启用多路复用。

Go HTTP client 连接复用必须设的三个 Transport 参数
不配 MaxIdleConns、MaxIdleConnsPerHost 和 IdleConnTimeout,http.Client 就算走默认连接池,也大概率在高并发下卡死或泄漏连接。
-
MaxIdleConns控制整个 client 能缓存多少空闲连接;设太小(如默认 0 或 2)会导致频繁新建连接,TLS 握手压垮 CPU -
MaxIdleConnsPerHost是每个域名/端口对的上限;HTTP/1.1 默认只允许 2 个,不改就成瓶颈,尤其调用多个下游服务时 -
IdleConnTimeout决定空闲连接多久后被主动关闭;建议 30–90 秒,比服务端IdleTimeout略短,避免客户端拿着已断开的连接还往里发请求
漏掉任意一个,都可能在 QPS 上千后出现 net/http: request canceled (Client.Timeout exceeded) 或 dial tcp: lookup failed 类错误——不是网络问题,是连接池没管住。
为什么 resp.Body 不 close 就会拖垮连接复用
Go 的连接复用依赖一个隐式契约:resp.Body 必须被读完并显式 Close(),否则连接不会归还给池子,而是直接标记为“不可复用”。
- 即使你只取
resp.StatusCode,也得io.Copy(io.Discard, resp.Body); resp.Body.Close() - 用
defer resp.Body.Close()很危险:如果 handler 提前 return,defer还没执行,连接就卡住 - 更稳妥的是用
io.ReadAll(resp.Body)+resp.Body.Close()组合,或封装成工具函数统一处理
线上常见现象:监控看到 http.Transport.IdleConnMetrics 中 idle 数持续为 0,但 requests 持续上涨——八成是 Body 没关。
HTTP/2 复用比调参更直接,但有个硬门槛
HTTP/1.1 的 Keep-Alive 是伪并发:一个连接同一时间只能跑一个 request。真要单连接多路并发,必须上 HTTP/2,而 Go 要启用它,只有一条路:http.Server 必须跑在 TLS 上,且证书有效(自签名需客户端信任)。
- 纯
http.ListenAndServe(":8080", nil)永远协商不出 HTTP/2,ALPN 都不触发 - 用
http.ListenAndServeTLS启动,且证书链完整,客户端发起请求时带Upgrade: h2c或走 HTTPS,才能真正启用多路复用 - 注意 Nginx 做反代时,必须设
proxy_http_version 1.1+proxy_set_header Upgrade $http_upgrade,否则上游 Go 服务收不到升级头
很多团队花几天调 Transport 参数,结果发现把服务切到 HTTPS + 正确证书,QPS 直接翻倍——不是参数没用,是底层协议限制卡死了天花板。
SO_REUSEPORT 是万级连接的分水岭
当并发连接稳定超过 5000,你会发现 accept() 系统调用开始排队,netstat -s | grep -i "listen overflows" 出现非零值,这是内核 listen queue 溢出的信号。此时单靠调协程数或缓冲区已经无效。
- 必须用
net.ListenConfig{Control: func(fd uintptr) { syscall.SetsockoptInt32(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1) }}显式开启 - 搭配
runtime.GOMAXPROCS(runtime.NumCPU()),让每个 listener 绑定到独立 OS 线程 - Docker/K8s 环境下,若没开
hostNetwork: true或用hostPort,SO_REUSEPORT会被 namespace 隔离机制屏蔽,白配
这个优化不在应用逻辑层,但它决定了你的 Go 服务能不能真正吃满多核——连 accept 都抢不过来,后面所有 handler 优化都是空中楼阁。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











