Nginx平滑升级与回滚
Nginx平滑升级
为什么要对 Nginx 平滑升级?
Nginx作为一般互联网系统的门户,承载着巨量的流量,同时Nginx版本迭代也越来越快,新版本功能更丰富,安全性也更高。线上业务不能停,此时 Nginx
的升级就是运维的工作了。
Nginx 自带的信号量机制方便地帮助我们实现了不停机的平滑升级。其原理简单概括,就是:
- 在不停掉旧进程的情况下,启动新进程。
- 旧进程负责处理仍然没有处理完的请求,但不再接受处理请求。
- 新进程接受新请求。
- 旧进程处理完所有请求,关闭所有连接后,停止进程。
一般有两种情况下需要升级 Nginx,一种是要升级 Nginx 的版本,另一种是要为 Nginx 添加新的模块
Nginx信号简介
Nginx是多进程模型,分为主进程与工作进程。
主进程支持的信号
TERM
,INT
:立刻退出QUIT
:等待工作进程结束后再退出KILL
:强制终止进程HUP
:重新加载配置文件,使用新的配置启动工作进程,并逐步关闭旧进程。USR1
:重新打开日志文件USR2
:启动新的主进程,实现热升级WINCH
:逐步关闭工作进程
工作进程支持的信号
TERM
,INT
:立刻退出QUIT
:等待请求处理结束后再退出USR1
:重新打开日志文件
有关文档官网链接:Controlling Nginx
Nginx 不停机平滑升级实战
- nginx-1.18.0 --> nginx-1.20.2
查看现有的 nginx 编译参数
/usr/local/nginx/sbin/nginx -V
- 注意是大写的
V
按照原来的编译参数安装 Nginx 的方法进行安装,只需要到 make
,千万不要 make install
。如果make install 会将原来的配置文件覆盖
本博文的 Nginx 编译参数为
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_stub_status_module \
--with-http_ssl_module
备份原 Nginx 二进制文件
备份二进制文件和 Nginx 的配置文件(期间Nginx不会停止服务)
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-1.18.0
复制新的 Nginx 二进制文件,进入新的 Nginx 源码包
cp /usr/local/nginx-1.20.2/objs/nginx /usr/local/nginx/sbin/
测试新版本的 Nginx 是否正常
/usr/local/nginx/sbin/nginx -t
给 Nginx 发送平滑迁移信号
若不清楚pid路径,请查看 Nginx 配置文件
cat /var/run/nginx/nginx.pid
# 或者
ps -ef | grep nginx
发送信号
kill -USR2 $(cat /var/run/nginx/nginx.pid)
此时在/var/run/nginx
下会出现一个nginx.pid.oldbin文件,存放旧master进程的pid
关闭旧的 Nginx 工作进程
kill -WINCH $(cat /var/run/nginx/nginx.pid.oldbin)
结束主进程,完成此次升级(可选)
kill -QUIT $(cat /var/run/nginx/nginx.pid.oldbin)
Nginx 版本回滚
对于升级来说,最难的不是升级,而是回滚,因为在实际生产环境回滚的机率是存在,比如:新版本由于某些未知bug导致与现有应用不兼容、或出现运行不稳定的情况等等。
所以,对运维工程师来说,故障回滚是重点。
在上面的结果中,我们也能看到老的master进程是一直存在,在没有手工关闭前,它是不会自已关闭的,这种设计是有好处的,好处就是为了升级新版本后,如果出现问题能及时快速的回滚到上一个稳定版本。
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-1.20.2
mv /usr/local/nginx/sbin/nginx-1.18.0 /usr/local/nginx/sbin/nginx
kill -HUP $(cat /var/run/nginx/nginx.pid.oldbin)
kill -WINCH $(cat /var/run/nginx/nginx.pid)
- 注意:新版本的主进程也没有关闭,同时nginx.pid中的pid也会变成回滚版本的