worker_shutdown_timeout 是防止旧 worker 进程卡在 shutting down 的关键配置,必须置于 main 块,值需匹配最长连接生命周期并协同 proxy/client 超时设置。

要让 Nginx 热重载(nginx -s reload)时旧 worker 进程不卡在 shutting down 状态、不挂起长连接,关键不是“让它慢慢退”,而是给它一个明确的退出时限——worker_shutdown_timeout 就是这道安全阀。它不保证连接永远不断,但能防止旧进程无限等待,把资源拖垮。
必须放在 main 块,否则完全不生效
这个指令只在全局上下文(即 nginx.conf 最外层)有效:
- ✅ 正确写法:
worker_shutdown_timeout 90s;(直接写在配置文件开头,events/http 之前) - ❌ 错误写法:
http { worker_shutdown_timeout 60s; }或events { ... }块内——Nginx 会静默忽略
值要匹配你的最长连接生命周期
设太短,上传中段、WebSocket 心跳间隙、慢查询可能被硬杀;设太长,旧进程堆积,内存和句柄耗尽。参考这些典型场景:
- 普通 REST API(P99 ≤ 1s):15–30s 足够覆盖抖动和慢查
- Keep-Alive 或长轮询(空闲超时通常 5–75s):45–90s,略大于
keepalive_timeout - WebSocket / SSE / HTTP/2 流:至少 90s~300s,建议 ≥ 心跳间隔 × 2 + RTT(例如心跳 30s → 设 90s 起步)
- 大文件上传(如 200MB @ 512KB/s ≈ 400s):worker_shutdown_timeout 至少设为 450s,并确保
client_body_timeout ≥ 450
单设 timeout 不行,必须闭环上下游超时
它只管“旧 worker 最多陪多久”,不管下游或客户端是否配合。若其他超时更早触发,照样断连:
-
proxy_read_timeout和proxy_send_timeout必须 ≥worker_shutdown_timeout,否则反向代理会在后端响应前主动关连接 -
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 后直接降级为短连接
验证它真起作用,别只看语法对
最直接的办法:写个延时响应接口,reload 同时发起请求,观察是否完整返回:
- 加测试 location:
location /slow { return 200 "done after 25s\n"; } - 执行
nginx -s reload,立刻用curl http://yourhost/slow请求 - 如果返回成功且无中断,说明 timeout 已生效;如果报错或超时,检查位置、单位、配套超时是否匹配











