Nginx 生产环境平滑升级实战:从 1.24.0 到 1.28.0 的零宕机操作全记录

在生产环境中升级 Nginx 一直是运维人们最谨慎的操作之一,因为它通常直接暴露在公网,承载着大量的流量,任何一点宕机或配置错误都可能造成业务影响。本文记录了一次真实的线上 Nginx 升级过程:从 1.24.0 升级到 1.28.0 ,全程实现零宕机,并且采用最安全的"二进制文件替换"方式,避免在生产机器上编译。

一、背景与环境

  • 机器信息:CentOS 7(内核 3.10),源码编译安装的 Nginx

  • binary 路径/usr/local/nginx/sbin/nginx

  • 配置路径/etc/nginx/(配置文件为 /etc/nginx/nginx.conf

  • 当前版本:nginx/1.24.0

  • 目标版本:nginx/1.28.0

  • 运行方式 :手动启动(非 systemd 管理),但进程手动启动也长期正常运行

  • 特点:无第三方动态模块,编译参数相对简单

二、为什么选择"只替换 binary"的方式?

常见的 Nginx 升级方式有三种:

  1. 直接在生产机源码编译 + make install

    风险:需要安装开发工具、下载源码、长时间编译,万一依赖缺失或编译失败,可能影响运行中的服务。

  2. 使用 yum/apt 等包管理升级

    不适用:本机为源码安装,无 RPM 包。

  3. 在测试机编译新 binary,只拷贝可执行文件替换 (本次采用)

    优点:

    • 生产机几乎不执行高风险操作
    • 只传输一个几 MB 的二进制文件
    • 支持 Nginx 官方推荐的热二进制替换,实现真正零宕机
    • 保持原有配置、日志、权限完全不变nginx文档

三、升级全过程详解

步骤 1:备份(永远的第一步)

在生产机上备份旧 binary:

bash 复制代码
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-v1.24.0

步骤 2:获取当前编译参数(最关键!)

javascript 复制代码
# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --with-pcre-jit --with-http_ssl_module --with-http_v2_module --with-http_sub_module --with-stream --with-stream_ssl_module

输出中重点复制 configure arguments 那一长串(包括 --prefix=/usr/local/nginx),确保新版本用完全相同的参数编译,否则可能缺少模块或路径不一致。

步骤 3:在测试机编译新版本(环境需一致)

选择一台系统、gcc 版本、库版本相近的测试机。

bash 复制代码
cd /tmp
wget https://nginx.org/download/nginx-1.28.0.tar.gz
tar zxvf nginx-1.28.0.tar.gz
cd nginx-1.28.0

./configure [粘贴上面完整的 configure arguments]

make -j$(nproc)    # 快速并行编译(后面的nproc是指最多用多少个核心去编译,如果不写似乎默认是1)

关键提醒不要执行 make install!

编译完成后,新 binary 位于:

bash 复制代码
./objs/nginx

验证版本:

bash 复制代码
./objs/nginx -v
# 输出:nginx version: nginx/1.28.0

步骤 4:传输并替换生产机 binary

bash 复制代码
# 从测试机拷贝到生产机的 /tmp
scp objs/nginx root@生产机IP:/tmp/nginx

# 生产机上替换
cd /usr/local/nginx/sbin
mv /tmp/nginx ./
# 直接覆盖或先备份旧的后再 mv
chmod 755 nginx

步骤 5:验证配置与版本

bash 复制代码
/usr/local/nginx/sbin/nginx -t
# 输出 syntax is ok 和 test is successful

/usr/local/nginx/sbin/nginx -V
# 确认显示 nginx/1.28.0,且 configure arguments 与之前一致

步骤 6:平滑重载(零宕机升级)

bash 复制代码
/usr/local/nginx/sbin/nginx -s reload

原理:Nginx master 进程收到 reload 信号后,会启动新的 worker 进程(使用新 binary),旧 worker 处理完当前连接后自动退出,整个过程无连接中断。

在这一步其实只是用了新的worker,而nginx的架构是master+worker的,但是master的话只是负责读取和校验配置文件、绑定 80/443 等特权端口、创建、管理、监控 worker 进程等,实际上几乎不占资源,如果要重载master的话,可以进行重启操作:

shell 复制代码
$/usr/local/nginx/sbin/nginx -s quit

# 等待一段时间,等到nginx相关进程全部停下来,除了 grep 本身,什么都不应该有
$ps -ef | grep nginx

# 重启nginx
$/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf

四、背后的核心原理

  1. Nginx 的 master-worker 架构

    master 进程负责读取配置、管理 worker;worker 负责实际处理请求。reload 时 master 启动新 worker,旧 worker 优雅退出。

  2. 二进制热替换支持

    Nginx 在启动时会将自身可执行文件路径记录下来。即使你替换了磁盘上的 binary 文件,正在运行的 master 进程仍使用旧的内存镜像。但 reload 后,新 worker 会加载新的 binary,从而实现版本升级。

  3. 为什么只换 binary 就行?

    Nginx 的模块大部分是静态编译进 binary 的(本次无动态模块)。只要编译参数一致,新 binary 就能完美适配原有配置和路径。

五、收尾与建议

  • 观察 /var/log/nginx/error.log 一段时间,确保无异常
  • 可选:切换为 systemd 管理,便于开机自启和统一操作
  • 保留旧 binary 至少一周,以备回滚

六、总结

这次升级全程不到 20 分钟,服务无任何感知,真正实现了生产环境的平滑升级。核心经验就是:

  • 备份永远第一位
  • 编译参数必须一模一样(尤其是 --prefix)
  • 优先选择"只替换 binary"的最小侵入方式
  • 利用 Nginx 自身平滑重载机制实现零宕机

这种方法特别适合老旧生产环境、源码安装、无包管理的场景咯

相关推荐
苹果醋33 小时前
vue + iview + vue-i18n中英翻译
java·运维·spring boot·mysql·nginx
OnlyEasyCode3 小时前
Linux部署Nginx前后端web教程
linux·前端·nginx
IvyWangT3 小时前
Uvicorn的多进程&Nginx的负载均衡 区别
nginx·负载均衡
程序员爱德华6 小时前
Nginx 服务器
nginx
咸鱼加辣1 天前
【nginx面试题】nginx虚拟
运维·nginx·github
全栈工程师修炼指南1 天前
Nginx | HTTPS 加密传输:Nginx 反向代理与上游服务 SSL 双向认证实践
网络·数据库·nginx·https·ssl
苹果醋31 天前
JAVA设计模式之策略模式
java·运维·spring boot·mysql·nginx
linweidong2 天前
顺丰运维面试题及参考答案
运维·nginx·容器·ansible·运维开发·防火墙·python面试
MonkeyKing_sunyuhua2 天前
ubuntu22.04安装nginx
运维·windows·nginx