必须在main块配置worker_shutdown_timeout(如90s),并同步调大proxy_read/send_timeout、合理设置client_*_timeout及WebSocket相关参数,才能确保旧worker在超时后强制退出,避免连接滞留。

要解决 Nginx 热加载(nginx -s reload)时旧 worker 进程长期卡在 shutting down 状态、无法及时退出的问题,核心是正确启用并配置 worker_shutdown_timeout —— 它不是可选项,而是长连接场景下防止资源滞留的必要安全阀。
必须放在 main 块,否则完全不生效
该指令仅在全局上下文(即 nginx.conf 最外层)有效,写在 events、http 或 server 块内会被忽略:
- ✅ 正确位置:
worker_shutdown_timeout 90s; - ❌ 错误写法:
events { worker_shutdown_timeout 30s; }或http { worker_shutdown_timeout 60s; } - 单位支持
s(秒)、m(分),如2m、300s
设太短会断连,设太长会卡死,得按业务定值
它不控制新连接接入,只决定旧 worker 在收到 QUIT 信号后,最多还能“陪”已有连接走多远。超时后强制退出,避免无限等待:
- 普通 REST API(P99 ≤ 1s):设为 15–30s,覆盖网络抖动和慢查
- 启用了 Keep-Alive 或长轮询:建议 45–90s,略大于
keepalive_timeout(通常 75s) - WebSocket / SSE / HTTP/2 流:至少 90s~300s,需大于心跳间隔 × 2 + RTT;例如心跳 30s,设
90s起步 - 大文件上传(如 200MB @ 512KB/s):理论耗时约 400s,
worker_shutdown_timeout至少设为 450s,并同步确认client_body_timeout ≥ 450
单独配置不够,必须闭环上下游超时
只调大 worker_shutdown_timeout 不解决问题,若下游或上游提前断开,旧 worker 仍会被“悬停”:
-
proxy_read_timeout和proxy_send_timeout必须 ≥worker_shutdown_timeout,否则 Nginx 会在后端响应前主动关闭连接 -
client_header_timeout和client_body_timeout应 ≤worker_shutdown_timeout,防止客户端迟迟不发完头或体,把旧 worker 卡住 - 若用 WebSocket,务必配齐:
proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
验证是否真正起作用
最直接的方式是模拟一个长响应,reload 同时发起请求,观察是否完整返回而非中断:
- 在
server块中加测试 location:location /slow { return 200 "done after 25s\n"; } - 执行
nginx -t && nginx -s reload - 用
curl -v http://your-domain/slow发起请求,若 25 秒后成功返回,说明机制已生效 - 检查日志:
grep "shutting down" /var/log/nginx/error.log,确认进程未长时间滞留


















