keepalive_timeout 仅控制客户端空闲连接最大等待时长,超时即关闭连接,不干预传输中请求、不防中间设备断连;需与 upstream keepalive、worker_shutdown_timeout、tcp 探测等协同实现优雅中断处理。

keepalive_timeout 本身不直接“处理”连接中断,而是通过控制空闲连接的生命周期,间接降低中断发生概率、缩短中断影响范围,并为优雅收尾创造条件。真正实现“优雅”,靠的是它与 upstream keepalive、worker_shutdown_timeout、TCP 层探测等机制的协同。
明确它的作用边界:不是防断,而是控空闲
keepalive_timeout 只管一件事:客户端发完一个请求后,Nginx 等待下一个请求的最长时间。超时即关闭连接(发 FIN),但它不干预正在传输中的请求,也不决定连接是否被中间设备静默切断。
- 它只作用于 Nginx 与客户端之间,不影响 upstream 连接
- 每次收到新请求,计时器重置——不是从连接建立开始倒计时
- 设为 0 表示禁用长连接,所有响应都带 Connection: close
配合 upstream keepalive,避免后端侧中断连锁反应
客户端连接中断不可控,但 Nginx 主动关掉上游连接,就容易引发 502 错误。必须让两端超时节奏匹配:
- 确认后端(如 Spring Boot、Node.js)真正启用 keep-alive,并设置好自身超时(例如 Spring Boot 的 server.tomcat.keep-alive-timeout=60)
- Nginx 的 keepalive_timeout 建议设为比后端值小 5–10 秒(如后端 60s,Nginx 设 50s),确保 Nginx 先主动关闭,而非等待后端 RST
- 在 upstream 块中启用连接池:keepalive 32;,并搭配 proxy_http_version 1.1; 和 proxy_set_header Connection '';
结合 worker_shutdown_timeout,实现 reload 零中断
日常 reload 配置时,旧 worker 进程若立即退出,正在复用的 keep-alive 连接就会被 RST 中断。这时 keepalive_timeout 要“让步”给更上层的退出机制:
- 必须配置 worker_shutdown_timeout 30s;(建议略大于 proxy_read_timeout)
- keepalive_timeout 应 ≥ 60s(例如设为 75s),保证 reload 前已建立的长连接不会被提前关闭
- 这样旧 worker 在 shutdown 窗口内继续服务现有连接,新请求由新 worker 接管,用户无感
加一层 TCP 探测,主动发现防火墙静默断连
很多“中断”其实来自中间网络设备(防火墙、NAT、云 LB)在空闲后直接丢包,不通知两端。此时 keepalive_timeout 束手无策,需启用底层保活:
- 开启 proxy_socket_keepalive on 240s 10s 3;(idle 240s 后每 10s 探一次,3 次失败即关 socket)
- 该值应略小于你所处环境的防火墙空闲超时(通常 300–600s,取 70%~80% 较稳妥)
- 必须与 proxy_http_version 1.1 和 proxy_set_header Connection '' 同时启用才生效
监控连接状态,验证是否真正“优雅”
调完参数不等于生效。要看真实连接行为:
- 用 ss -tnpo | grep :443 | grep ESTAB | wc -l 查看活跃连接数,对比峰值是否合理(过千需警惕堆积)
- 查 error log 是否仍有 upstream prematurely closed connection 或 Connection reset by peer
- 用 nginx_stub_status 观察 Waiting 连接占比:过高说明空闲连接多、复用率低,可能 timeout 过长或客户端不配合
- 抓包确认客户端是否真发了 Connection: keep-alive,且响应头中有 Keep-Alive: timeout=xx











