nginx负载均衡热升级需协同二进制热升级与后端节点灰度切流:前者通过usr2/winch/quit信号实现新旧master共存过渡,后者借助weight调整、down标记或健康检查模块(如nginx_upstream_check_module)完成平滑切流。

在 Nginx 中管理负载均衡集群节点的热升级切换,核心是两层协同:一是单台 Nginx 实例自身的二进制热升级(不中断服务),二是整个 upstream 集群中后端节点的平滑切流(避免请求失败)。两者不能混为一谈,但必须配合使用才能实现真正的“零感知”切换。
单台 Nginx 的二进制热升级
这是保障反向代理层自身高可用的基础。关键不是重启,而是让新旧 master 进程共存过渡:
- 编译新版本时,必须指定与旧版完全一致的 --prefix 路径(如 /usr/local/nginx),否则 pid、log、conf 路径错位会导致 reload 失败
- 备份原二进制:
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.oldbin - 拷入新二进制:
cp ~/nginx-1.24.0/objs/nginx /usr/local/nginx/sbin/ - 发 USR2 信号启动新 master:
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`—— 此时新旧 master 同时运行,新 worker 开始监听端口 - 确认新进程就绪后,发 WINCH 信号优雅关闭旧 worker:
kill -WINCH `cat /usr/local/nginx/logs/nginx.pid` - 验证无误再发 QUIT 关闭旧 master:
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
upstream 后端节点的灰度切流
当你要升级的是被代理的应用服务器(比如一组 Java 服务),Nginx 本身不自动“知道”哪台正在升级,需人工干预流量调度:
- 在 upstream 块中为每个 server 显式设置 weight 和 max_fails/fail_timeout,例如:
server 10.1.1.21:8080 weight=5 max_fails=2 fail_timeout=30s; - 升级前,先临时降低目标节点权重(如从 5 改为 1)或加
down标记,再执行nginx -t && nginx -s reload - 观察 access.log 和 error.log 确认该节点已无新请求接入,再停机升级
- 升级完成后,恢复权重并 reload,Nginx 会自动将其重新纳入轮询
自动健康检查 + 切换(需扩展模块)
Nginx 开源版默认只做被动容错(连接失败后跳过),要实现主动探测+自动摘除,需引入第三方模块:
- 推荐使用 nginx_upstream_check_module(Tengine 衍生模块),支持 HTTP 探针
- 配置示例:
upstream backend {<br> server 10.1.1.21:8080;<br> server 10.1.1.22:8080;<br> check interval=3 rise=2 fall=5 timeout=1 type=http;<br> check_http_send "HEAD /health HTTP/1.0\r\n\r\n";<br> check_http_expect_alive http_2xx http_3xx;<br>} - 该配置会让 Nginx 每 3 秒发一次健康检查请求,连续 5 次失败则标记为 down,恢复后自动加回
集群级自动切换(结合脚本与配置生成)
像小绿叶技术博客所用的方案,本质是把“节点状态判断 → 配置重写 → reload”封装成自动化流程:
- 用 Bash 或 Python 定期 ping 或 curl 各后端 IP+端口,记录存活状态
- 根据存活列表动态生成 upstream 块(如仅保留 .21、.23,排除 .22)
- 生成完整 nginx.conf 后,执行
nginx -t校验 +nginx -s reload - 可进一步集成 Let’s Encrypt 自动续签和 HTTPS 配置注入,形成闭环











