目标
nginx -s reload 会让新 worker 以新配置启动,并通知旧 worker 处理完手头请求后退出。做得对,进行中的请求毫发无伤,变更对客户端完全不可见。失败模式都很具体且可修:应用侧撕断 upstream 连接,或某个卡死的下载让古老 worker 永生。两者都只差一条指令。
步骤要点
- 记录 reload 前的 worker PID 列表作为基线。
- 让 hey 持续打流量,流量进行中执行 nginx -t && nginx -s reload,统计非 200 响应数。
- 五秒后再取 PID 列表,与基线求交集:交集为空说明旧 worker 已排空退出。
- 配置 worker_shutdown_timeout 10s 与 upstream keepalive,让慢客户端最多阻塞十秒、上游连接复用不误伤。
- 用 nginx -T 渲染最终配置核对变更确实生效,而不是 reload 成功但配置没变。
排错提示
reload 期间仍出 502 多是应用侧不优雅,要给 upstream 开 keepalive 并确认应用能排空连接;旧 worker 滞留几分钟是长请求挂住,务必设 worker_shutdown_timeout;reload 返回成功但行为没变,是配置校验失败而 nginx 保留了旧配置——前后都要跑 nginx -t 并读错误日志。
适用边界
reload 只换 worker,无法应用需要二进制升级的变更(如 nginx 大版本);WebSocket 等长连接可能被 shutdown_timeout 掐断,需与客户端重连逻辑协同。
代码示例
# The graceful handover
pgrep -f "nginx: worker" > /tmp/before
nginx -t && nginx -s reload
sleep 5
pgrep -f "nginx: worker" > /tmp/after
comm -12 /tmp/before /tmp/after | wc -l # 0 = old workers drained