idletimeout是服务端keep-alive连接空闲等待上限,非请求处理时限;它与readheadertimeout协同防御慢速攻击,且须小于负载均衡器空闲超时以避免连接重置。

IdleTimeout 是服务器端空闲连接的“待岗时长”上限
它不是整个请求的处理时限,也不是读/写阶段的耗时限制,而是专用于 Keep-Alive 连接:当一个 HTTP/1.1 连接完成一次请求响应后进入空闲状态,IdleTimeout 就开始倒计时。一旦超时,服务器会主动关闭该 TCP 连接。
默认值是 0(即不限制),这在生产环境极易导致文件描述符耗尽、TIME_WAIT 堆积或被负载均衡器静默断连。必须显式设置,常见值为 60 * time.Second 或 90 * time.Second。
- 它和
ReadTimeout、WriteTimeout完全正交:后两者管单次请求的读写耗时,IdleTimeout只管“没活干”的等待时间 - 若你设了
IdleTimeout = 30s,但客户端每 25 秒发一次请求,连接就能一直复用;若某次间隔达 35 秒,连接就会被关掉 - HTTP/2 连接也受此控制——Go 的
IdleTimeout对两种协议都生效
为什么只设 IdleTimeout 不够,还必须配 ReadHeaderTimeout
仅靠 IdleTimeout 无法防御慢速攻击(如 slowloris)或畸形请求头。因为连接建立后,只要还没开始读 header,IdleTimeout 就不启动;而 ReadHeaderTimeout 从 accept 连接那一刻就开始计时,专门卡住“只建连不发 header”的恶意行为。
-
ReadHeaderTimeout默认也是0,建议设为2 * time.Second~5 * time.Second - 如果只设
IdleTimeout而忽略ReadHeaderTimeout,攻击者可用极低速率发送请求头,长期占住连接却不触发空闲超时 - 二者配合:先用
ReadHeaderTimeout快速拦截坏连接,再用IdleTimeout清理真正空闲的好连接
IdleTimeout 和负载均衡器(如 AWS ALB/NLB)的协同问题
服务端 IdleTimeout 必须小于 LB 的空闲超时,否则 LB 会在服务器之前把连接“悄悄断开”,下次复用时客户端收到 net/http: HTTP/1.x transport connection broken 或直接 EOF。
- AWS ALB 默认空闲超时是
60s,所以你的IdleTimeout应设为 ≤55s - GCP HTTP(S) Load Balancing 默认是
30s,对应服务端应 ≤25s - 若 LB 配置不可控(如第三方 SaaS),更稳妥的做法是把
IdleTimeout设得保守些(如30s),并确保客户端http.Transport.IdleConnTimeout也同步下调
连接被踢出时,客户端看到的错误不是 timeout
当服务器因 IdleTimeout 主动关闭连接,客户端下一次复用该连接发起请求时,通常不会报 context deadline exceeded 或 timeout,而是更底层的 I/O 错误:
-
read: connection reset by peer(Linux) -
use of closed network connection(Go 运行时内部提示) -
net/http: HTTP/1.x transport connection broken(http.Transport检测到写失败后的包装错误)
这类错误容易被误判为网络抖动或服务端崩溃,实际只是空闲策略不匹配。排查时优先核对服务端 IdleTimeout 与客户端 IdleConnTimeout、LB 空闲配置三者是否形成梯度关系。











