零停机热升级依靠Nginx主进程响应USR2/WINCH/QUIT信号,实现新旧二进制共存与进程平滑交接;需验证新二进制语法路径兼容、保留旧二进制备份、检查ABI兼容性,三者缺一不可。

零停机热升级不是靠重启实现的,而是靠 Nginx 主进程对信号的响应能力,配合新旧二进制共存与进程平滑交接完成的。核心在于不中断监听套接字、不丢弃已有连接、不强制终止正在处理的请求。
升级前必须验证三件事
跳过任一环节都可能导致服务短暂中断或配置加载失败:
-
新二进制语法与路径兼容:用新二进制执行
nginx -t -c /etc/nginx/nginx.conf,确保能正确读取原配置、日志目录、pid 文件路径;若提示找不到 conf 或权限拒绝,说明安装前缀(--prefix)或用户属组不一致 -
保留旧二进制并备份:执行
cp /usr/sbin/nginx /usr/sbin/nginx.oldbin,避免覆盖后无法回滚;新二进制建议先放为独立路径(如/usr/sbin/nginx-1.24.0),确认无误再软链替换 -
检查 ABI 兼容性:小版本升级(如 1.22.1 → 1.22.3)通常安全;跨大版本(如 1.20.x → 1.24.x)需确认是否移除了你依赖的模块(如
ngx_http_v2_module),否则新 master 启动会失败
三步信号驱动的进程切换
整个过程不重启、不 reload、不 touch 监听端口,全由信号触发内部调度:
-
发 USR2 启动新主进程:执行
kill -USR2 $(cat /var/run/nginx.pid)。此时旧 master 自动将 pid 文件重命名为nginx.pid.oldbin,并 fork 出新 master 进程,后者加载新二进制、启动新 worker,开始接受新连接 -
发 WINCH 关闭旧 worker:执行
kill -WINCH $(cat /var/run/nginx.pid.oldbin)。旧 master 收到后不再派发新请求给旧 worker,但允许它们完成当前请求(受worker_shutdown_timeout控制,默认 10 秒) -
发 QUIT 终止旧 master:等旧 worker 全部退出后(
ps aux | grep "worker process" | grep -v new无输出),执行kill -QUIT $(cat /var/run/nginx.pid.oldbin),彻底清理旧主进程
升级后快速验证与回滚准备
不能只看进程是否存在,要确认实际行为已变更:
-
查运行中的二进制路径:运行
ls -l /proc/$(pgrep -f "nginx: master process")/exe,输出应指向新版本路径(如/usr/sbin/nginx-1.24.0) -
测关键配置生效点:比如你升级是为了修复某个 header 行为,用
curl -I http://localhost | grep X-确认响应头已更新;若仍返回旧值,说明新 worker 未接管或配置未重载 -
保留回滚通道:升级后不要立即删除
nginx.oldbin和nginx.pid.oldbin;若发现异常(如大量 502、SSL 握手失败),可立刻向新 master 发QUIT,再用旧二进制启动:/usr/sbin/nginx.oldbin -c /etc/nginx/nginx.conf
不复杂但容易忽略。











