worker_shutdown_timeout是解决Nginx重载时旧worker卡在shutting down状态的关键配置,必须置于main块,值需匹配最长连接生命周期,并与proxy/client超时参数闭环对齐。

平滑重载(nginx -s reload)时 worker 卡在 shutting down 状态,常见诱因不是配置没生效,而是旧 worker 正在陪一个“永远收不到响应”的后端连接耗尽生命周期——比如后端已失联但 Nginx 还在等它回包。关键不在“等不等”,而在“等多久、谁来叫停”。
看日志确认是否真卡住
别只盯 ps aux | grep nginx 里有没有 shutting down 进程。先查错误日志是否有线索:
-
重点搜:
open socket left in connection或aborting—— 表明 worker 被强制杀掉,连接没清理完,是卡死后的典型后遗症 - 搜
upstream timed out或no live upstreams—— 暴露后端不可达,且超时未及时触发清理 - 搜
worker process is shutting down后长时间无退出记录 —— 结合时间戳判断是否超预期停留(比如 >60s)
验证 worker_shutdown_timeout 是否真正生效
这个指令是解卡的“保险丝”,但它极易配错位置或孤立使用:
- 必须放在 main 块(即
events和http外层),和user、pid、worker_processes同级;写进http或upstream里会被静默忽略 - 值要匹配业务最长连接场景:普通 API 设 30s,长轮询设 90s,WebSocket 至少 120s;若后端已失联,这个值就是旧 worker 的“最后通牒”
- 单设它没用:必须同步检查
proxy_connect_timeout、proxy_read_timeout、proxy_send_timeout是否 ≤ 它 —— 否则上游超时会提前掐断,但旧 worker 仍可能卡在读 header 阶段
模拟失联后端,实测重载行为
用可控方式复现,比猜更可靠:
- 在某个
location里加一个故意延迟且不返回的代理:
location /hang { proxy_pass http://unreachable:8080; proxy_read_timeout 300; }
- 启动 Nginx 后,用
curl -v http://localhost/hang &发起请求,再立刻执行nginx -s reload - 观察:旧 worker 是否在
worker_shutdown_timeout设定时间后自动退出?还是持续卡住?如果卡住,说明 timeout 未生效或被其他超时覆盖
联动检查上下游超时闭环
worker 卡死常因“多层超时打架”:某一层提前断连,另一层还在傻等。必须对齐三组参数:
-
客户端侧:
client_header_timeout和client_body_timeout应 ≤worker_shutdown_timeout,防慢客户端拖住读阶段 -
代理侧:
proxy_connect_timeout(建连)、proxy_send_timeout(发体)、proxy_read_timeout(收响应)全部 ≥worker_shutdown_timeout,确保后端失联时由它统一裁决退出时机 -
后端健康:启用
max_fails=1 fail_timeout=10s,让 Nginx 尽快标记失联节点,避免重试加重卡顿











