阅读量:5
平滑升级和回滚
有时候我们需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时 Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级
1. 平滑升级流程
- 平滑升级四个阶段
- 只有旧版nginx的master和worker进程
- 旧版和新版nginx的master和worker进程并存,由旧版nginx接收处理用户的新请求
- 旧版和新版nginx的master和worker进程并存,由新版nginx接收处理用户的新请求
- 只有新版nginx的master和worker进程
将旧Nginx二进制文件换成新Nginx程序文件(注意先备份) 向master进程发送USR2信号启动新nginx进程 master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin master进程用新Nginx文件启动新master进程及worker子进程成为旧master的子进程 系统中将有新旧两个Nginx主进程和对应的worker子进程并存 当前新的请求仍然由旧Nginx的worker进程进行处理 将新生成的master进程的PID存放至新生成的pid文件nginx.pid 向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止 向旧master进程发送QUIT信号,关闭旧master,并删除Nginx.pid.oldbin文件 如果发现升级有问题,可以回滚∶向旧master发送HUP,向新master发送QUIT
2. 平滑升级和回滚案例
# 在nginx编译安装的基础上(可以参考编译安装脚本) # 下载最新稳定版 [root@Ubuntu2204 ~]#wget https://nginx.org/download/nginx-1.26.1.tar.gz [root@Ubuntu2204 ~]#tar xvf nginx-1.26.1.tar.gz [root@Ubuntu2204 ~]#cd nginx-1.26.1/ # 查看当前使用的版本及编译选项 [root@Ubuntu2204 nginx-1.26.1]#nginx -V nginx version: nginx/1.22.1 built by gcc 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) built with OpenSSL 3.0.2 15 Mar 2022 TLS SNI support enabled configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module # configure arguments后面是以前编译时的参数。现在编译使用一样的参数 # 开始编译新版本 [root@Ubuntu2204 nginx-1.26.1]#./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module # 只要make无需要make install [root@Ubuntu2204 nginx-1.26.1]#objs/nginx -v nginx version: nginx/1.26.1 # 查看两个版本 [root@Ubuntu2204 nginx-1.26.1]#ll objs/nginx /apps/nginx/sbin/nginx -rwxr-xr-x 1 nginx nginx 5884536 Jul 12 09:43 /apps/nginx/sbin/nginx* -rwxr-xr-x 1 root root 6013648 Jul 12 10:04 objs/nginx* # 把之前的旧版的nginx命令备份 [root@Ubuntu2204 nginx-1.26.1]#cp /apps/nginx/sbin/nginx /opt/nginx.old # 把新版本的nginx命令复制过去覆盖旧版本程序文件,注意:需要加 -f 选项强制覆盖,否则会提示Text file busy [root@Ubuntu2204 nginx-1.26.1]#cp -f ./objs/nginx /apps/nginx/sbin/ # 检测一下有没有问题 [root@Ubuntu2204 nginx-1.26.1]#/apps/nginx/sbin/nginx -t nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful # 发送信号USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的nginx # 此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80 # 此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。 [root@Ubuntu2204 nginx-1.26.1]#kill -USR2 `cat /apps/nginx/logs/nginx.pid` # 可以看到两个master,新的master是旧版master的子进程,并生成新版的worker进程 [root@Ubuntu2204 ~]#ps auxf | grep nginx root 904 0.0 0.0 10168 944 ? Ss 09:48 0:00 nginx: master process /apps/nginx/sbin/nginx nginx 906 0.0 0.1 10904 3684 ? S 09:48 0:00 \_ nginx: worker process root 5234 0.0 0.3 10188 6416 ? S 10:15 0:00 \_ nginx: master process /apps/nginx/sbin/nginx nginx 5235 0.0 0.1 10924 3716 ? S 10:15 0:00 \_ nginx: worker process root 5240 0.0 0.1 6480 2240 pts/1 S+ 10:16 0:00 | \_ grep --color=auto nginx [root@Ubuntu2204 ~]#lsof -i :80 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 904 root 6u IPv4 31463 0t0 TCP *:http (LISTEN) nginx 906 nginx 6u IPv4 31463 0t0 TCP *:http (LISTEN) nginx 5234 root 6u IPv4 31463 0t0 TCP *:http (LISTEN) nginx 5235 nginx 6u IPv4 31463 0t0 TCP *:http (LISTEN) # 先关闭旧nginx的worker进程,而不关闭nginx主进程方便回滚 # 向原Nginx主进程发送WINCH信号,它会逐步关闭旗下的工作进程(主进程不退出),这时所有请求都会由新版Nginx处理 [root@Ubuntu2204 nginx-1.26.1]#kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin` # 如果旧版worker进程有用户的请求,会一直等待处理完后才会关闭 [root@Ubuntu2204 ~]#ps auxf | grep nginx root 904 0.0 0.0 10168 944 ? Ss 09:48 0:00 nginx: master process /apps/nginx/sbin/nginx root 5234 0.0 0.3 10188 6416 ? S 10:15 0:00 \_ nginx: master process /apps/nginx/sbin/nginx nginx 5235 0.0 0.1 10924 3716 ? S 10:15 0:00 \_ nginx: worker process ##################### 注意:此处如果是虚拟机先做快照方便回滚 #################### # 经过一段时间测试,新版本服务没问题,最后发送QUIT信号,退出老的master [root@Ubuntu2204 nginx-1.26.1]#kill -QUIT `cat /apps/nginx/logs/nginx.pid.oldbin` # 查看版本是不是已经是新版了 [root@Ubuntu2204 nginx-1.26.1]#nginx -v nginx version: nginx/1.26.1 [root@Ubuntu2204 nginx-1.26.1]#curl -I 127.0.0.1 HTTP/1.1 200 OK Server: nginx/1.26.1 Date: Fri, 12 Jul 2024 02:28:11 GMT Content-Type: text/html Content-Length: 615 Last-Modified: Fri, 12 Jul 2024 01:43:39 GMT Connection: keep-alive ETag: "66908a4b-267" Accept-Ranges: bytes
# 回滚 (虚拟机恢复之前做的快照) [root@Ubuntu2204 ~]#ps aux | grep nginx root 904 0.0 0.0 10168 944 ? Ss 09:51 0:00 nginx: master process /apps/nginx/sbin/nginx root 5234 0.0 0.3 10188 6416 ? S 10:18 0:00 nginx: master process /apps/nginx/sbin/nginx nginx 5235 0.0 0.1 10924 3716 ? S 10:18 0:00 nginx: worker process root 5659 0.0 0.1 6612 2252 pts/3 S+ 10:31 0:00 grep --color=auto nginx # 如果升级的版本发现问题需要回滚,可以发送HUP信号,重新拉起旧版本的worker [root@Ubuntu2204 ~]#kill -HUP `cat /apps/nginx/logs/nginx.pid.oldbin` [root@Ubuntu2204 ~]#ps aux | grep nginx root 904 0.0 0.0 10168 944 ? Ss 09:51 0:00 nginx: master process /apps/nginx/sbin/nginx root 5234 0.0 0.3 10188 6416 ? S 10:18 0:00 nginx: master process /apps/nginx/sbin/nginx nginx 5235 0.0 0.1 10924 3716 ? S 10:18 0:00 nginx: worker process nginx 5661 0.0 0.1 10904 3684 ? S 10:32 0:00 nginx: worker process root 5663 0.0 0.1 6612 2240 pts/3 S+ 10:32 0:00 grep --color=auto nginx [root@Ubuntu2204 ~]#pstree -p | grep nginx |-nginx(904)-+-nginx(5234)---nginx(5235) | `-nginx(5661) # 最后关闭新版的master [root@Ubuntu2204 ~]#kill -QUIT `cat /apps/nginx/logs/nginx.pid` # 恢复旧版的文件 [root@Ubuntu2204 ~]#mv /opt/nginx.old /apps/nginx/sbin/nginx