基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

如何在不停止服务的情况下,对 Nginx 进行热升级(平滑升级)?

对 Nginx 进行不中断服务的平滑升级(热升级),是 Nginx 核心架构(Master-Worker 进程模型)带来的一项非常实用的特性。

整个过程的核心思想是:启动新的 Nginx Master 进程 -> 让新进程接管请求 -> 优雅地关闭旧 Worker 进程 -> 关闭旧 Master 进程。

以下是详细的操作步骤:

核心信号说明

在开始前,你需要了解几个关键的 Nginx 信号:

  • USR2:平滑升级可执行程序。告诉旧 Master 进程,准备升级。
  • WINCH:优雅地关闭 Worker 进程。
  • QUIT:优雅地关闭 Master 进程。
  • HUP:重新加载配置文件(在回滚时会用到)。

第一步:准备新版本的 Nginx

  1. 查看当前版本和编译参数
    记录下当前的编译参数,保证新版本拥有相同的模块。

    bash
    /usr/local/nginx/sbin/nginx -V

    注意输出的 configure arguments: 后面的内容并复制下来。

  2. 下载并解压新版本源码

    bash
    wget http://nginx.org/download/nginx-1.x.x.tar.gz
    tar -zxvf nginx-1.x.x.tar.gz
    cd nginx-1.x.x
  3. 配置和编译
    使用第一步复制的 configure arguments 进行配置。

    bash
    ./configure [你的旧编译参数]

    然后进行编译:

    bash
    make

    ⚠️ 极其重要:绝对不要执行 make install,否则会覆盖现有的配置文件和目录!


第二步:替换 Nginx 二进制文件

  1. 备份旧的二进制文件

    bash
    mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
  2. 拷贝新的二进制文件到 sbin 目录
    在刚刚编译的源码目录下(objs 目录中存放着新编译的二进制文件):

    bash
    cp objs/nginx /usr/local/nginx/sbin/nginx
  3. 测试新二进制文件与旧配置的兼容性

    bash
    /usr/local/nginx/sbin/nginx -t

    确保输出 syntax is oktest is successful


第三步:发送信号进行平滑升级

  1. 查找当前(旧)Nginx 的 Master 进程 PID

    bash
    ps -ef | grep nginx

    或者直接查看 pid 文件:

    bash
    cat /usr/local/nginx/logs/nginx.pid

    假设查到的旧 Master PID 是 1111

  2. 发送 USR2 信号:启动新 Master 进程

    bash
    kill -USR2 1111

    此时系统会发生以下事情:

    • 旧 Nginx 会将当前的 .pid 文件重命名为 .pid.oldbin
    • 旧 Nginx 会使用新的二进制文件启动一个新的 Master 进程(假设 PID 为 2222)和新的 Worker 进程。
    • 此时,新旧 Nginx 同时运行,共同处理请求。
  3. 发送 WINCH 信号:优雅关闭旧 Worker 进程

    bash
    kill -WINCH 1111

    此时系统会发生以下事情:

    • 旧的 Master 进程会告诉它的 Worker 进程:“处理完手头的请求后就退出”。
    • 等待一段时间后,所有的旧 Worker 进程都会退出。
    • 此时,只有新的 Worker 进程在处理请求,旧的 Master 进程依然存活(以防需要回滚)。

第四步:确认与收尾

  1. 观察运行状态
    检查业务是否正常访问。使用 ps -ef | grep nginx 查看进程状态,你应该只能看到一个旧的 Master,一个新的 Master,以及新的 Worker 进程。

  2. 发送 QUIT 信号:关闭旧 Master 进程(最终完成升级)
    如果你确信新版本运行完美,没有问题,就可以关闭旧的 Master 进程了。

    bash
    kill -QUIT 1111

    至此,平滑升级彻底完成。


🚨 附录:如果升级失败,如何平滑回滚?

如果在执行到 第三步的第3小步(旧 Worker 已关闭,旧 Master 还在)时,发现新版本有问题,可以按照以下步骤无损回滚:

  1. 拉起旧的 Worker 进程
    发送 HUP 信号给旧的 Master 进程(PID: 1111),它会重新启动旧的 Worker 进程。

    bash
    kill -HUP 1111
  2. 优雅关闭新的 Master 进程及其 Worker
    发送 QUIT 信号给新的 Master 进程(PID: 2222)。

    bash
    kill -QUIT 2222
  3. 恢复二进制文件

    bash
    mv /usr/local/nginx/sbin/nginx.old /usr/local/nginx/sbin/nginx

    回滚完成。

00:00
00:00