Nginx 平滑升级

Nginx 平滑升级(Ubuntu 24.04 环境)

一、平滑升级核心原理

Nginx 平滑升级通过向主进程发送特定信号实现,核心优势是不中断现有请求处理

  • 新请求逐步由新版本 Worker 进程接管;
  • 旧 Worker 进程处理完现有连接后优雅退出;
  • 全程保持服务可用,无连接拒绝或请求中断;
  • 核心信号机制:通过 USR2/WINCH/QUIT 等信号实现新旧进程的无缝切换,而非直接重启服务。

二、前置准备

2.1 环境检查(核心基础)

  1. 查看当前 Nginx 版本和编译参数(新版本必须复用完全一致的编译参数,仅修复语法错误):

    bash 复制代码
    nginx -v  # 查看版本(示例:1.24.0)
    nginx -V  # 查看编译参数(完整复制,后续编译新版本用,关键!)

    实操示例输出:

    bash 复制代码
    root@Ubuntu24-13:~# nginx -v
    nginx version: nginx/1.24.0 (Ubuntu)
    root@Ubuntu24-13:~# nginx -V
    nginx version: nginx/1.24.0 (Ubuntu)
    built with OpenSSL 3.0.13 30 Jan 2024
    TLS SNI support enabled
    configure arguments: --with-cc-opt='-g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/build/nginx-WLuzPu/nginx-1.24.0=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -fdebug-prefix-map=/build/nginx-WLuzPu/nginx-1.24.0=/usr/src/nginx-1.24.0-2ubuntu7.5 -fPIC -Wdate-time -D_FORTIFY_SOURCE=3' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-mail_ssl_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-http_geoip_module=dynamic --with-http_image_filter_module=dynamic --with-http_perl_module=dynamic --with-http_xslt_module=dynamic --with-mail=dynamic --with-stream=dynamic --with-stream_geoip_module=dynamic
  2. 确保 Nginx 进程数充足(便于测试升级效果):

    bash 复制代码
    # 安装编辑器(若未安装)
    apt install vim -y
    # 编辑配置文件
    vim /etc/nginx/nginx.conf
    # 修改 worker_processes 为 2(原若为 auto 则改为固定值,便于观察进程切换)
    worker_processes 2;
    # 重载配置(不中断服务)
    nginx -s reload
    # 验证进程数
    ps aux | grep nginx

    实操示例输出(需看到 1 个 Master + 2 个 Worker 进程):

    bash 复制代码
    root@Ubuntu24-13:~# nginx -s reload
    2025/12/16 21:32:12 [notice] 3100#3100: signal process started
    root@Ubuntu24-13:~# ps aux | grep nginx
    root        2580  0.0  0.3  59440 13676 ?        S    21:13   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
    www-data    3101  0.0  0.1  60264  6284 ?        S    21:32   0:00 nginx: worker process
    www-data    3102  0.0  0.1  60264  6176 ?        S    21:32   0:00 nginx: worker process
    root        3104  0.0  0.0  17832  2340 pts/0    S+   21:32   0:00 grep --color=auto nginx

2.2 全量依赖环境准备(解决所有编译报错)

编译新版本需安装全量依赖(覆盖所有模块,避免 xslt、image_filter、geoip、perl 等模块编译报错):

bash 复制代码
apt update && apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev perl libperl-dev libxml2 libxml2-dev libxslt1-dev libgd-dev libpng-dev libjpeg-dev libfreetype6-dev libgeoip-dev curl

针对性解决依赖兼容问题

报错场景 解决命令
Perl 库报错 libperl.so 找不到 find / -name libperl.so* && ln -s /usr/lib/x86_64-linux-gnu/libperl.so.5.38 /usr/lib/x86_64-linux-gnu/libperl.so(版本按实际修改)
GeoIP 模块报错 GeoIP library not found apt install -y libgeoip-dev
image_filter 模块报错 GD library not found apt install -y libgd-dev libpng-dev libjpeg-dev
xslt 模块报错 libxml2/libxslt libraries not found apt install -y libxml2-dev libxslt1-dev

2.3 下载新版本源码(版本选择原则)

  • 优先小版本升级(如 1.24.0 → 1.25.0),避免跨大版本(如 1.18 → 1.25)的兼容性问题;
  • 仅下载官方源码包,拒绝第三方修改包,保证安全性。
bash 复制代码
# 创建统一目录结构(便于管理)
mkdir -p /data/softs /data/server/nginx/backup
cd /data/softs
# 下载新版本(以 1.25.0 为例,可替换为目标版本)
wget http://nginx.org/download/nginx-1.25.0.tar.gz
# 校验包完整性(可选,推荐生产环境执行)
md5sum nginx-1.25.0.tar.gz  # 对比官网公布的 MD5 值
# 解压
tar xf nginx-1.25.0.tar.gz
cd nginx-1.25.0

三、编译新版本 Nginx(核心避坑)

3.1 复用旧版本编译参数(仅修复1处关键错误)

nginx -V 输出的 configure arguments: 后的参数完整复制,仅移除 --with-ld-opt 末尾的 -fPIC(这是 Ubuntu 系统编译的核心语法错误,其余参数完全保留),执行以下命令:

bash 复制代码
./configure --with-cc-opt='-g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=/build/nginx-WLuzPu/nginx-1.24.0=. -flto=auto -ffat-lto-objects -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -fdebug-prefix-map=/build/nginx-WLuzPu/nginx-1.24.0=/usr/src/nginx-1.24.0-2ubuntu7.5 -fPIC -Wdate-time -D_FORTIFY_SOURCE=3' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-mail_ssl_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-http_geoip_module=dynamic --with-http_image_filter_module=dynamic --with-http_perl_module=dynamic --with-http_xslt_module=dynamic --with-mail=dynamic --with-stream=dynamic --with-stream_geoip_module=dynamic

3.2 编译(仅编译,绝对禁止执行 make install!)

bash 复制代码
make  # 仅编译二进制文件,不覆盖系统现有配置和程序

编译耗时约1-2分钟,编译完成后,新版本二进制文件位于 ./objs/nginx

3.3 编译后验证(必做)

bash 复制代码
# 验证版本是否正确
./objs/nginx -v  # 应输出 nginx/1.25.0
# 验证配置加载是否正常
./objs/nginx -t -c /etc/nginx/nginx.conf  # 用新版本验证现有配置

实操示例输出:

bash 复制代码
root@Ubuntu24-13:/data/softs/nginx-1.25.0# ./objs/nginx -v
nginx version: nginx/1.25.0
root@Ubuntu24-13:/data/softs/nginx-1.25.0# ./objs/nginx -t -c /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

四、平滑升级操作(分步执行,全程可回滚)

4.1 备份旧版本二进制文件(安全第一)

bash 复制代码
# 备份旧版本(带时间戳,便于追溯)
mv /usr/sbin/nginx /usr/sbin/nginx-$(nginx -v 2>&1 | awk -F '/' '{print $2}')-$(date +%Y%m%d)
# 替换为新版本二进制文件
cp /data/softs/nginx-1.25.0/objs/nginx /usr/sbin/nginx
# 赋予执行权限(确保 root 可执行)
chmod +x /usr/sbin/nginx
# 验证版本(此时仅替换文件,进程仍为旧版本)
nginx -v  # 输出 nginx/1.25.0

4.2 启动新版本 Master 进程(核心步骤)

  1. 获取旧版本 Master 进程 PID:

    bash 复制代码
    old_pid=$(cat /run/nginx.pid)
    echo "旧 Master PID:$old_pid"

    实操示例输出:

    bash 复制代码
    root@Ubuntu24-13:/data/softs/nginx-1.25.0# old_pid=$(cat /run/nginx.pid)
    root@Ubuntu24-13:/data/softs/nginx-1.25.0# echo "旧 Master PID:$old_pid"
    旧 Master PID:2580
  2. 发送 USR2 信号,启动新版本 Master 进程:

    bash 复制代码
    kill -USR2 $old_pid
  3. 验证进程状态(此时应存在新旧两个 Master 进程):

    bash 复制代码
    ps auxf | grep nginx
    ls /run/nginx.pid*  # 旧 PID 文件会被重命名为 nginx.pid.oldbin

    正常输出特征:

    bash 复制代码
    root        2580  0.0  0.3  59440 13676 ?        S    21:13   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;  # 旧 Master
    www-data    3101  0.0  0.1  60264  6284 ?        S    21:32   0:00  \_ nginx: worker process
    www-data    3102  0.0  0.1  60264  6176 ?        S    21:32   0:00  \_ nginx: worker process
    root       22771  0.0  0.1  11060  7016 ?        S    22:26   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;  # 新 Master
    www-data   22772  0.0  0.1  12808  4360 ?        S    22:26   0:00  \_ nginx: worker process
    www-data   22773  0.0  0.1  12808  4488 ?        S    22:26   0:00  \_ nginx: worker process

4.3 优雅关闭旧 Worker 进程(新请求接管)

发送 WINCH 信号,让旧 Master 关闭其 Worker 进程,新请求全部由新版本 Worker 处理:

bash 复制代码
kill -WINCH $old_pid
# 验证新版本接管服务(核心验证)
curl -I 127.0.0.1 | grep Server  # 应输出 nginx/1.25.0

4.4 确认升级完成(彻底退出旧 Master)

  • 建议观察 1-5 分钟(生产环境可延长至 10-15 分钟),确认业务无异常后再执行;
  • 若期间出现问题,可立即执行回滚操作(见第五章)。
bash 复制代码
# 优雅退出旧 Master 进程
kill -QUIT $old_pid
# 最终验证进程(仅保留新版本 Master + Worker)
ps auxf | grep nginx

正常输出示例:

bash 复制代码
root       22771  0.0  0.1  11060  7016 ?        S    22:26   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data   22772  0.0  0.1  12808  4360 ?        S    22:26   0:00  \_ nginx: worker process
www-data   22773  0.0  0.1  12808  4488 ?        S    22:26   0:00  \_ nginx: worker process

五、平滑回滚(新版本异常时,秒级恢复)

若新版本出现卡顿、502、配置报错等问题,立即执行以下步骤回滚至旧版本:

5.1 恢复旧版本二进制文件

bash 复制代码
# 替换回旧版本二进制(以 1.24.0 为例,按实际备份名修改)
mv /usr/sbin/nginx /usr/sbin/nginx-1.25.0
mv /usr/sbin/nginx-1.24.0-20251216 /usr/sbin/nginx

5.2 重启旧版本 Worker 进程

bash 复制代码
# 获取旧 Master PID(升级时保留的 oldbin 文件)
old_master_pid=$(cat /run/nginx.pid.oldbin)
# 拉起旧 Worker 进程
kill -HUP $old_master_pid

5.3 退出新版本 Master 进程

bash 复制代码
new_master_pid=$(cat /run/nginx.pid)
kill -QUIT $new_master_pid

5.4 验证回滚结果

bash 复制代码
# 进程仅保留旧版本
ps auxf | grep nginx
# 请求返回旧版本标识
curl -I 127.0.0.1 | grep Server  # 输出 nginx/1.24.0

六、高频问题解决方案

问题现象 根因 解决方案
USR2 信号发送后,无新 Master 进程启动 1. 新版本二进制替换错误;2. 配置校验失败;3. 动态模块版本不兼容 1. 验证 nginx -v 为新版本;2. 执行 nginx -t 修复配置;3. 禁用不兼容模块:mkdir -p /etc/nginx/modules-enabled/bak && mv /etc/nginx/modules-enabled/*.conf /etc/nginx/modules-enabled/bak/
配置校验报错 module xxx.so version 1024000 instead of 1025000 系统预装的动态模块(如 geoip2、image_filter)是针对旧版本编译的,与新版本主程序不兼容 方案1(快速):禁用不兼容模块(如上);方案2(恢复功能):重新编译模块:cd /data/softs/nginx-1.25.0 && ./configure nginx -V 2>&1
configure 报错"xxx library not found" 缺少对应模块的依赖库 对照 2.2 节安装依赖,非关键提示(如 sys/filio.h not found/dev/poll not found)可忽略
新请求被拒绝/端口未监听 1. 新版本配置错误;2. 端口被占用 1. nginx -t 修复配置;2. `netstat -tulpn
Perl 模块编译失败 缺少 Perl 开发库或软链接错误 apt install -y libperl-dev + 重新创建 libperl.so 软链接
编译时报 flto=auto 错误 GCC 版本兼容问题 将编译参数中的 -flto=auto -ffat-lto-objects 改为 -flto

七、关键注意事项

7.1 版本与参数规范

  1. 编译参数:仅移除 --with-ld-opt 末尾的 -fPIC,其余参数必须与旧版本完全一致,否则信号机制会失效;
  2. 版本选择:优先小版本迭代,跨大版本升级前必须在测试环境验证至少 72 小时;
  3. 模块兼容:第三方动态模块(如 GeoIP2、Lua)必须与 Nginx 主程序版本完全一致(1.25.0 主程序需搭配 1.25.0 模块)。

7.2 信号说明(核心操作对照表)

信号 作用 适用场景
USR2 启动新版本 Master 进程 升级第一步,启动新版本但不影响旧版本
WINCH 关闭旧 Master 的 Worker 进程 升级第二步,让新版本接管新请求
HUP 重启 Worker 进程(重载配置) 回滚时拉起旧 Worker 进程,或重载配置
QUIT 优雅退出 Master 进程 升级完成后退出旧 Master,或回滚时退出新版本 Master
TERM/KILL 强制终止进程 仅紧急故障时使用(会中断请求)

7.3 生产环境最佳实践

  1. 升级前:备份配置文件(cp -r /etc/nginx /data/server/nginx/backup/nginx-conf-$(date +%Y%m%d))和二进制文件;
  2. 升级中:先在测试环境验证,再灰度升级(如先升级1台应用服务器),最后全量升级;
  3. 升级后:观察日志(tail -f /var/log/nginx/error.log)、进程状态、业务指标(QPS、响应时间)至少 24 小时;
  4. 清理:升级完成后清理编译源码(rm -rf /data/softs/nginx-1.25.0),仅保留二进制备份。

7.4 合规与安全

  1. 仅使用官方源下载 Nginx,避免第三方篡改包;
  2. 编译完成后验证二进制文件的属主和权限(必须为 root:root,权限 755);
  3. 升级后执行安全扫描(如 nginx -T 检查配置漏洞、端口扫描验证监听状态)。

八、后续优化

8.1 恢复扩展模块功能(如需 GeoIP2/image_filter 等)

bash 复制代码
# 重新编译适配新版本的模块
cd /data/softs/nginx-1.25.0
./configure `nginx -V 2>&1 | grep -o '--with-.*'`  # 复用编译参数
make modules  # 仅编译模块,不覆盖主程序
# 替换旧模块文件
cp objs/*.so /usr/share/nginx/modules/
# 恢复模块配置并验证
mv /etc/nginx/modules-enabled/bak/*.conf /etc/nginx/modules-enabled/
nginx -t && nginx -s reload

8.2 清理无用依赖

bash 复制代码
apt autoremove -y  # 卸载自动安装的无用依赖
apt clean  # 清理缓存

8.3 长期维护

  1. 定期备份 Nginx 配置和二进制文件;
  2. 关注官方安全更新,及时小版本升级修复漏洞;
  3. 建立升级操作手册,标准化流程,避免人工失误。
相关推荐
亚林瓜子2 小时前
mysql命令行手动导入csv数据到指定表
数据库·mysql·gui·csv·cli·db·import
水库浪子95272 小时前
工作中常用函数详解与示例-PostgreSQL(其他数据库可能函数不一致)
数据库
每日学点SEO3 小时前
「网站新页面冲进前10名成功率下降69%」:2025 年SEO竞争格局分析
大数据·数据库·人工智能·搜索引擎·chatgpt
哈__3 小时前
时序数据库性能巅峰对决:金仓数据库在复杂场景下的技术突破与实战验证
数据库
WayserKON3 小时前
pg 窗口函数
数据库·postgresql
!chen3 小时前
Oracle回滚与撤销技术
数据库·oracle
总有刁民想爱朕ha3 小时前
Windows Server 2019部署PostgreSQL 14教程
数据库·windows·postgresql
聆风吟º3 小时前
时序数据战场巅峰对决:金仓数据库 VS InfluxDB深度解析
数据库·influxdb·kingbasees·金仓数据库
动亦定4 小时前
微服务中如何保证数据一致性?
java·数据库·微服务·架构