平滑升級和回滾
- 1. 平滑升級流程
- 2. 平滑升級和回滾案例
有時候我們需要對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