nginx 平滑重启 vs 平滑升级

本文介绍了Nginx的平滑重启和平滑升级机制,解析了其背后的技术原理,包括多进程架构、信号处理机制,以及如何通过命令行进行操作。同时探讨了第三方插件dyups的应用场景。

1. nginx 架构

在总结了 nginx 配置以后,发现 nginx 可以做到平滑重启和升级,即在重启和升级的过程中服务不间断。于是怀着好奇的心情,开始了探索 nginx 的平滑重启和平滑升级是如何实现的。先解释下笔者对这两个名词的概念:

  • 平滑重启:针对的是更新 nginx 的 *.conf 文件
  • 平滑升级: 针对的是 nginx 服务的二进制文件更新,比如版本升级或者引入三方的模块重新编译

在正式理解这两个概念之前,需要先了解 nginx 的架构,架构如下图所示:

在这里插入图片描述

nginx 采用多进程的方式,包括一个 master 进程和多个子进程。其中 master 进程主要负责:加载配置项、启动工作进程及非停服务升级,worker 进程处理网络请求及响应( worker 进程基于异步及非阻塞的事件驱动模型提供服务)。

异步非阻塞的事件驱动模型单独解释

2. nignx 的 signal 支持

2.1 master 支持的 signal

TERM, INTQuick shutdown
QUITGraceful shutdown
KILLHalts a stubborn process
HUPConfiguration reloadStart the new worker processes with a new configurationGracefully shutdown the old worker processes
USR1Reopen the log files
USR2Upgrade Executable on the fly
WINCHGracefully shutdown the worker processes

2.2 worker 支持的 signal

There’s no need to control the worker processes yourself. However, they support some signals (意思是这些信号量无需手动处理,但是也能够被 worker 进程支持)

TERM, INTQuick shutdown
QUITGraceful shutdown
USR1Reopen the log files

3. nginx 平滑重启

3.1 nginx -s reload 命令

nginx -s reload 命令等价于kill HUP $(cat /usr/local/nginx/logs/nginx.pid) ,该信号会触发 master 进程完成以下工作:

  • 检查更新后的配置文件是否正确
  • 如正确,创建新的 worker 进程,新 worker 进程创建成功后,发送信号给旧 woker 进程使之优雅关闭。
  • 如错误,仍旧使用未更新之前的配置

笔者手动实验了一波,见下图:

在这里插入图片描述

  • 第一次 ps -ef | grep nginx 可观察到当前有一个 master 进程和两个 worker 进程。
  • 执行nginx -s reload 命令后,第二次 ps -ef | grep nginx ,观察到两个 woker 进程的进程 id 有变化。
  • 更改 nginx.conf 文件后,执行nginx -s reload 命令后,第二次 ps -ef | grep nginx ,观察到 worker 进程进程仅剩一个并且进程 id 有变化。

笔者在首次执行 nginx -s reload 的时候,并未变更任何配置,但还是重新产生了两个进程,很好奇这里为什么不检查一下配置有无变更?(待解答,后续补充……)

3.2 ngx_http_dyups_module

nginx reload 操作会影响到长连接,使用 dyups 模块可以避免 reload 操作。dyups(dyups means dynamic upstreams) 是github上一个nginx相关的开源插件,可以在不reload nginx的情况下动态更新upstream。

笔者没用上述插件,具体如何使用可以查看我们客服系统中使用tengine+dyups+consul 解决自动扩容缩容的问题

4. nginx 平滑升级

笔者翻看了 nginx 的源码,发现对 upgrade 指令的定义如下:

build:
	\$(MAKE) -f $NGX_MAKEFILE

install:
	\$(MAKE) -f $NGX_MAKEFILE install

modules:
	\$(MAKE) -f $NGX_MAKEFILE modules

upgrade:
	$NGX_SBIN_PATH -t

	kill -USR2 \`cat $NGX_PID_PATH\`
	sleep 1
	test -f $NGX_PID_PATH.oldbin

	kill -QUIT \`cat $NGX_PID_PATH.oldbin\`

4.1 平滑升级执行步骤

  • 更换新版本的二进制文件

  • 发送 SIGUSR2 信号给 master 进程,信号触发执行重命名 .pid 为 .oldbin(e.g. /usr/local/nginx/logs/nginx.pid.oldbin),执行新的二进制文件,即重启新的 master 和 worker 进程

在这里插入图片描述

  • 上图看到 2 组 nginx 实例在运行,共同处理接收到的请求,此时需要优雅停止旧 worker 进程,即发送 WINCH 信号给旧 master 进程

在这里插入图片描述

  • 观察一段时间后,发现只有新 worker 进程在提供服务,旧 woker 进程已经终止

在这里插入图片描述

  • 如上图所示,此时有两个 master 进程同时存在,笔者觉得 nginx 这里的设计很好,就好像铅笔后面的橡皮擦、购物后的七天无理由退货,给你足够的时间,让你有机会反悔。按照如下步骤执行

    • 1—— 发送 HUP 信号给旧 master 进程,它将重启 worker 进程
    • 2 —— 发送 QUIT 或者 TERM 或者 QUIT 给新 master 进程终止新 worker 进程
    • 3 —— 最后旧 master 进程将会移除 .oldbin 后缀,一切又恢复到反悔之前的状态啦
  • 如果升级的没有问题,发送 QUIT 信号给旧 master 进程,升级过程结束

在这里插入图片描述

5.思考

笔者的思考如下:

  • nginx 作为知名开源代码,提供的三方开源插件是真的多,只有你想不到,没有人家没写过的。
  • tengine 和 OpenResty 基于 nginx 开发,在 nginx 的基础上提供了更多因地制宜的定制化功能,比如上面的 dyups 已经合并到了 tengine 的代码仓库。
  • nginx 的源码是真的多啊…………

6.参考资料

<think>好的,用户想了解如何进行Nginx平滑升级以及注意事项。我需要先整理一下之前提供的引用内容,看看有哪些关键步骤和注意点。 首先,根据引用[1],平滑升级的方法主要是向原Nginx主进程发送HUP信号,这样可以重新启动工作进程,同时继续使用旧版本的配置文件。但这里可能有点混淆,因为引用[4]提到的是USR2信号来启动新版本,然后使用WINCH信号逐步停止旧进程。需要确认正确的信号使用方式。 再看引用[2],里面提到两种方案,用户关注的是第二种,即平滑升级。步骤包括编译新版本、替换二进制文件、发送信号。引用[3]给出了具体的命令示例,比如解压、配置、编译安装,这可能涉及覆盖旧版本的可执行文件吗?或者是否需要将新版本的安装路径分开? 引用[4]详细描述了信号的使用流程:USR2启动新服务,WINCH停止旧的工作进程,之后可能需要发送QUIT信号来完全关闭旧的主进程。这里需要注意的是,新旧版本会同时运行一段时间,确保新版本没问题后再关闭旧的。 接下来需要综合这些信息,整理出步骤清晰的流程。首先,用户需要下载新版本的Nginx源码,进行编译,注意配置参数要与旧版本一致,这点在注意事项里很重要,否则可能出现兼容问题。然后,替换二进制文件,通常是将新编译的nginx文件复制到旧版本的安装目录下。接着,发送USR2信号给旧的主进程,启动新进程。此时,系统会有两个主进程,旧的和新的。确认新版本运行正常后,发送WINCH信号给旧的主进程,让其优雅停止工作进程。如果出现问题,可以回滚,即重新使用旧进程并reload。 注意事项方面,必须确保编译时的参数一致,包括模块,否则新版本可能缺少必要的功能。同时,每一步都要检查nginx的状态,使用nginx -v或nginx -V查看版本和参数。此外,备份旧版本二进制文件也是关键,以便快速回滚。还有,升级过程中要监控服务状态,确保没有请求丢失。 用户可能的疑问点包括信号的具体作用,如何验证配置参数是否一致,以及回滚的具体步骤。需要把这些细节清晰地呈现出来,避免用户操作时出错。同时,要强调测试的重要性,建议在测试环境先演练一遍,再在生产环境操作。 最后,生成的相关问题应该围绕升级后的验证、常见错误处理、参数对比方法等,帮助用户全面了解平滑升级的各个方面。</think>### Nginx平滑升级方法与注意事项 #### **一、平滑升级方法** 1. **准备新版本源码包** 下载新版本Nginx源码并解压: ```bash wget http://nginx.org/download/nginx-x.x.x.tar.gz tar zxvf nginx-x.x.x.tar.gz ``` 2. **编译新版本** 进入源码目录,**确保编译参数与原版本一致**(可通过 `nginx -V` 查看旧版本参数)[^3]: ```bash cd nginx-x.x.x ./configure --prefix=/usr/local/nginx --user=www --with-http_ssl_module # 其他参数需与旧版本一致 make # 仅编译,不执行make install ``` 3. **替换二进制文件** 备份旧版本二进制文件,替换为新编译的 `objs/nginx`: ```bash cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old cp objs/nginx /usr/local/nginx/sbin/nginx ``` 4. **发送信号触发升级** - 向旧主进程发送 `USR2` 信号,启动新版本主进程[^4]: ```bash kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid) ``` - 向旧主进程发送 `WINCH` 信号,逐步关闭旧工作进程: ```bash kill -WINCH $(cat /usr/local/nginx/logs/nginx.pid.oldbin) ``` 5. **验证与回滚** - 确认新版本运行正常后,关闭旧主进程: ```bash kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid.oldbin) ``` - 若需回滚,向旧主进程发送 `HUP` 信号重启旧进程,并强制终止新进程[^1]。 --- #### **二、注意事项** 1. **编译参数一致性** 必须通过 `nginx -V` 检查旧版本配置参数,确保新版本编译时包含所有原有模块(如缺少 `--with-http_ssl_module` 会导致HTTPS失效)[^3]。 2. **备份与版本验证** - 操作前备份配置文件和二进制文件。 - 升级后执行 `nginx -v` 和 `nginx -t` 验证版本及配置语法[^1]。 3. **信号操作顺序** 必须按 `USR2` → `WINCH` → `QUIT` 顺序发送信号,避免服务中断[^4]。 4. **并行运行风险** 新旧版本会短暂并行运行,需监控资源占用情况(如内存、CPU)。 5. **回滚预案** 保留旧版本二进制文件,若新版本异常,可通过旧文件快速回滚[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值