idletimeout必须显式设置,因其默认值为0(无限空闲),不设会导致空闲连接长期占用fd、内存和goroutine,引发too many open files等资源耗尽问题;http/1.1推荐设为30–60秒,并需与readtimeout、writetimeout协同配置,且须与客户端idleconntimeout对齐。
go自带http服务器的idletimeout不是可选优化项,而是生产环境必须显式设置的保命参数——默认值为0(无限空闲),不设就等于放任连接泄漏。
为什么IdleTimeout设成0会导致文件描述符耗尽
Go http.Server 默认不设 IdleTimeout,意味着只要客户端不主动断开、服务端就永远保持 Keep-Alive 连接打开。真实场景中,移动端网络抖动、Nginx 中间层异常断连、甚至用户直接关掉浏览器标签页,都会留下“半死不活”的空闲连接。这些连接持续占用 fd、内存和 goroutine,且不会被自动回收。
典型表现:lsof -i :8080 | wc -l 持续上涨,netstat -an | grep ESTABLISHED | wc -l 居高不下,dmesg 出现 too many open files 报错。
修复方式很简单:
- 必须显式设置
IdleTimeout,HTTP/1.1 推荐30 * time.Second到60 * time.Second - 不要依赖 Nginx 或 CDN 的超时配置——它们只管转发,Go 内部仍会傻等
- 若服务同时支持 HTTP/2,
IdleTimeout依然生效(用于控制连接空闲期,而非流级超时)
IdleTimeout 和 ReadTimeout / WriteTimeout 不是替代关系
这三个字段各自守一段生命周期,缺一不可,设错一个就可能让其他两个失效:
-
ReadTimeout:从 TCP 连接建立开始,到读完全部 request header + body 的总时间(含 slowloris 防护) -
WriteTimeout:从WriteHeader开始,到整个 response body 写完为止(含 handler 执行、DB 查询、模板渲染) -
IdleTimeout:连接已建立、请求已处理完、正等待下一个请求的“空闲窗口”
常见错误是只设了 ReadTimeout,但 handler 里有个卡住的 db.QueryRow,此时 WriteTimeout 才起作用;而如果这个响应发完了,之后连接挂那儿不动,就全靠 IdleTimeout 来收尾。
如何安全地启动并验证 IdleTimeout 是否生效
不能用 http.ListenAndServe,它底层用的是零值 http.Server,所有超时字段都是默认值。必须显式构造:
server := &http.Server{
Addr: ":8080",
Handler: myRouter(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 45 * time.Second,
}
log.Fatal(server.ListenAndServe())
验证是否生效的方法:
- 用
curl -v http://localhost:8080发一次请求,然后不关闭连接,等 46 秒后再发第二次——应收到Connection reset by peer - 抓包看 TCP 层:第一次响应后无数据,45 秒左右服务端发出 FIN 包
- 在 handler 里加
time.Sleep(50 * time.Second),观察连接是否在 45 秒空闲后被断开(注意这不是WriteTimeout触发的)
与客户端 IdleConnTimeout 协同时最容易忽略的对齐问题
服务端 IdleTimeout 和客户端 http.Transport.IdleConnTimeout 是一对镜像参数。不对齐会直接导致复用失败:
- 若服务端设
45s,客户端设90s→ 客户端拿着已失效连接重用 →read: connection reset by peer - 若服务端设
45s,客户端设10s→ 连接太早被客户端丢弃,复用率暴跌,建连开销上升
建议策略:先确认服务端 IdleTimeout 值,再把客户端 IdleConnTimeout 设为略小(如小 5–10 秒),并确保 MaxIdleConnsPerHost 足够(别卡在默认的 2)。
真正难的不是写那行 IdleTimeout: 45 * time.Second,而是意识到它必须和 Read/Write 超时一起设、和服务端部署拓扑(Nginx、LB、客户端 SDK)联动调优——漏掉任意一环,连接池就形同虚设。











