旧 worker 进程在 reload 后长期卡在 shutting down 状态是 Nginx 优雅退出的正常机制,但若持续数分钟不退、数量不减、连接不降,则说明存在阻滞点;需通过 ps、lsof、ss 等命令确认是否真卡住,并重点排查空闲 Keep-Alive、长响应流式连接及上游未返回请求三类拖慢因素,同时确保 worker_shutdown_timeout 在 main 块合理配置(如 90s),并与 proxy_read_timeout、client_body_timeout 等参数闭环对齐,严禁手动 kill -9,避免触发 abort 和 socket 残留。

旧 worker 进程在 reload 后长期卡在 shutting down 状态,不是异常,而是 Nginx 优雅退出机制的正常表现;但若持续数分钟不退、数量不减、连接不降,就说明存在阻滞点。排查关键在于定位“它还在等什么”。
一、确认是否真卡住,还是只是慢退出
执行以下命令观察进程状态和变化趋势:
-
ps aux | grep "nginx: worker process" | grep "shutting down"—— 查看有多少旧 worker 处于该状态 -
ps -eo pid,comm,lstart,etimes | grep nginx | sort -k4—— 按启动时间排序,识别明显早于 reload 时间的 worker -
watch -n 2 'lsof -p [worker_pid] 2>/dev/null | wc -l'—— 替换[worker_pid],持续观察某旧 worker 打开文件数(主要是 socket)是否缓慢下降
若数量/连接数稳定不降,或 lsof 计数长时间不变(如 60 秒无变化),才需深入排查。
二、重点检查三类“不肯走”的连接
旧 worker 只有在所有连接自然关闭后才会退出。以下三类连接最常拖住它:
-
空闲 Keep-Alive 连接:客户端保持 TCP 连接但未发新请求,会一直等到
keepalive_timeout(默认 75s)才断。用ss -tn state established '( dport = :80 )' | wc -l查看活跃连接中 idle 超过 30s 的比例 -
长响应或流式响应:如 SSE、HTTP/2 推送、大文件下载、
return 200 "slow"测试返回等。这类连接在响应完成前不会释放 -
上游未返回的请求:proxy 场景下,Nginx 已转发请求但后端迟迟不回,受
proxy_read_timeout控制;若该值远大于worker_shutdown_timeout,旧 worker 会被“悬停”等待
三、验证并调整超时参数闭环
单设 worker_shutdown_timeout 不够,必须匹配上下游实际耗时:
- 在 main 块(nginx.conf 最外层)配置:
worker_shutdown_timeout 90s;(非 events/http 内) - 确保
proxy_read_timeout和proxy_send_timeout≥ 上述值,否则 Nginx 主动断连反而触发重试或错误 - 检查
client_header_timeout和client_body_timeout≤worker_shutdown_timeout,防客户端慢速上传卡住旧进程 - WebSocket/SSE 必须配全:
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
改完后 nginx -t && nginx -s reload,再用慢请求复现测试(如访问 /slow 返回 25s 响应),观察是否完整返回且旧 worker 在 90s 内退出。
四、排除人为干预与资源残留干扰
这些操作会让问题恶化而非解决:
-
禁止手动 kill -9 旧 worker:会触发
open socket left in connection和 abort 告警,还可能引发连接中断或数据丢失 -
检查 error.log 是否有 reload 失败记录:如
bind() to 0.0.0.0:80 failed或invalid number of arguments,说明新配置根本没加载,旧 worker 实际仍在跑旧逻辑 -
确认系统资源充足:用
free -h、ulimit -n、cat /proc/sys/fs/file-nr排查内存、fd 耗尽导致新 worker 启动失败、旧 worker 无法正常收尾


















