nginx之程序热部署

nginx不停机做版本的升级,降级操作...

热部署

nginx信号:

https://nginx.org/en/docs/control.html

  • 主进程可接收信号
    • TERM , INT 快速关闭
    • QUIT graceful shutdown master 以及worker
    • HUP 重读配置文件,用于新的worker,并退出老的worker,即nginx -s reload
    • USR1 re-opening log files
    • USR2 更换可执行程序,(热切换时用)
    • WIHCH 只graceful shutdown worker
  • worker进程可接收信号
    • TERM INT 快速关闭
    • QUIT graceful shutdown
    • USR1 re-opening log files
    • WINCH abnormal termination for debugging (requires debug_points to be enabled)

升级

1,软链接方式,停机切换

若编译安装指定prefix带有版本号,可以通过软连接实现版本切换;**注意PATH变量,不能是带版本号的路径,而应该是软链接的路径**
初始版本
ln -sv /usr/local/nginx-1.14 /usr/local/nginx

升级:
ln -sv /usr/local/nginx-1.16 /usr/local/nginx

降级:
ln -sv /usr/local/nginx-1.12 /usr/local/nginx

nginx运行时,不能做软链接的删除,重新链接:所以要停机
原因:一旦改变软链接指向,nginx程序就变了,此时在发信号,是找不到与之对应的pid文件的,自然失败;

如下:16在线切为14,命令立刻变为14版本的,发信号是去找14版本目标下的pid,但此时是16版本的nginx在运行,16的才有pid文件;报错文件找不到,【所以软连接直接修改还是需要中断服务的】
[root@host2 nginx-1.16.1]# nginx -v
nginx version: nginx/1.14.2
[root@host2 nginx-1.16.1]# nginx -s reload
nginx: [error] open() "/usr/local/nginx-1.14/logs/nginx.pid" failed (2: No such file or directory)

2,用USR2信号,不中断服务切换版本

初始14版本;configure选择带版本号的路径,并做软链接;

升级为16版本,configure时选择带版本号的路径,升级时,修改软链接指向为新的;

注意:对configure时选项的需求

  • 多个版本的prefix要带版本号,然后做软链接到/usr/local/nginx
  • pid的唯一路径,针对1方式pid文件的问题,需要把多个configure的pid指定为相同的路径

14版本编译选项

./configure --prefix=/usr/local/nginx-1.14 --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio --with-stream_realip_module --with-stream_ssl_module --with-stream --with-pcre --with-http_gzip_static_module --with-http_realip_module --add-module=/usr/local/src/echo-nginx-module --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/subsys/nginx

[root@host2 nginx-1.14.2]# cat /var/run/nginx/nginx.pid 
30350
[root@host2 nginx-1.14.2]# cat /var/log/nginx/error.log 
[root@host2 nginx-1.14.2]# cat /var/log/nginx/access.log

16编译选项

和14的prefix必须不同,user group需要相同,选项根据需求自定义,重点是pid路径,2个日志路径,1个锁路径必须一致,新老nginx程序都读一个路径下的pid文件,才能完成在线的版本切换

[root@host2 nginx-1.16.1]# ./configure --prefix=/usr/local/nginx-1.16 --user=nginx --group=nginx --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/subsys/nginx


开始升级

  1. 软连接切换,从14切到16,此时nginx程序版本是16
  2. 对14实例的主进程发送USR2信号,作用提示更换程序文件,其实相当于将程序文件重装了一遍,只不过相同的路径,实际已经是16版本的程序了
    1. 此时2个版本的主-worker进程并存
    2. pid会更新,新旧pid文件并存
  3. 向旧pid文件发QUIT信号,会优雅停止旧的主进程及worker进程;
    1. 此时完成了在线切换
  4. **稳妥起见:**先发WINCH信号,只优雅停止旧的worker,旧的主进程保留,方便回退;
  5. 回退时:向旧的主进程发HUP信号,重新加载配置文件,fork出新的旧版本的worker进程,然后发QUIT信号给新版本的程序的pid,退出
    1. 此时完成了回退;

成功升级方法

reference:https://groups.google.com/g/openresty/c/HiV3c-JwTZ4

根据回答,上一节,每个版本设置不同路径,然后用相同软链接配置到PATH变量中,反而会影响在线升级

error.log报错:
[alert] 1284#1284: execve() failed while executing new binary process "nginx" (2: No such file or directory)

正常后error.log:
2020/08/28 11:48:01 [notice] 1371#0: using inherited sockets from "6;"

解决方法:直接将编译好的主程序文件,放在sbin目录下,替换原来的主程序,然后发送USR2信号;(不再利用不同版本做软链接的方法)

启动时一定用绝对路径,不用环境变量里的软链接路径

[root@host2 sbin]# /usr/local/nginx-1.14/sbin/nginx -v
nginx version: nginx/1.14.2
[root@host2 sbin]# /usr/local/nginx-1.14/sbin/nginx
[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1339      1  0 11:46 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1340   1339  0 11:46 ?        00:00:00 nginx: worker process
直接用绝对路径启动14版本的nginx

[root@host2 sbin]# ll
total 11952
-rwxr-xr-x 1 root root 8410944 Aug 27 19:13 nginx
-rwxr-xr-x 1 root root 3825016 Aug 28 11:06 nginx.16
[root@host2 sbin]# mv nginx nginx.14
[root@host2 sbin]# mv nginx.16 nginx
[root@host2 sbin]# ll
total 11952
-rwxr-xr-x 1 root root 3825016 Aug 28 11:06 nginx
-rwxr-xr-x 1 root root 8410944 Aug 27 19:13 nginx.14
更换主程序版本


[root@host2 sbin]# ll /var/run/nginx/
total 4
-rw-r--r-- 1 root root 5 Aug 28 11:46 nginx.pid
此时只有一个pid

[root@host2 sbin]# kill -USR2 `cat /var/run/nginx/nginx.pid`
[root@host2 sbin]# ll /var/run/nginx/
total 8
-rw-r--r-- 1 root root 5 Aug 28 11:48 nginx.pid
-rw-r--r-- 1 root root 5 Aug 28 11:46 nginx.pid.oldbin
发送信号后,生成新的pid,以及原有pid共存

[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1339      1  0 11:46 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1340   1339  0 11:46 ?        00:00:00 nginx: worker process
root       1371   1339  0 11:48 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1372   1371  0 11:48 ?        00:00:00 nginx: worker process
此时,2个版本的进程,主和worker都共存;

[root@host2 sbin]# kill -WIHCH `cat /var/run/nginx/nginx.pid.oldbin`
-bash: kill: WIHCH: invalid signal specification
[root@host2 sbin]# kill -s WINCH `cat /var/run/nginx/nginx.pid.oldbin`
[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1339      1  0 11:46 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
root       1371   1339  0 11:48 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1372   1371  0 11:48 ?        00:00:00 nginx: worker process
发送WINCH信号,先把旧的worker退出;

[root@host2 sbin]# kill -s QUIT `cat /var/run/nginx/nginx.pid.oldbin`
确认新版本工作正常一段时间,可以把旧的主进程也退出

[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1371      1  0 11:48 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1372   1371  0 11:48 ?        00:00:00 nginx: worker process
此时,只有新的16版本程序进程了

回滚/降级

和升级步骤相同:只是用低版本的14替换现在运行的高版本的16的主程序

升级未完成时回滚

[root@host2 sbin]# kill -USR2 `cat /var/run/nginx/nginx.pid`
[root@host2 sbin]# ll /var/run/nginx/
total 8
-rw-r--r-- 1 root root 5 Aug 28 12:22 nginx.pid
-rw-r--r-- 1 root root 5 Aug 28 12:13 nginx.pid.oldbin
[root@host2 sbin]# !ps
ps -ef |grep nginx |grep -v "grep"
root       1430      1  0 12:13 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1431   1430  0 12:13 ?        00:00:00 nginx: worker process
root       1458   1430  0 12:22 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1459   1458  0 12:22 ?        00:00:00 nginx: worker process
[root@host2 sbin]# kill -s WINCH `cat /var/run/nginx/nginx.pid.oldbin`
[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1430      1  0 12:13 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
root       1458   1430  0 12:22 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1459   1458  0 12:22 ?        00:00:00 nginx: worker process

[root@host2 sbin]# kill -s HUP `cat /var/run/nginx/nginx.pid.oldbin`
[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1430      1  0 12:13 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
root       1458   1430  0 12:22 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1459   1458  0 12:22 ?        00:00:00 nginx: worker process
nginx      1469   1430  0 12:23 ?        00:00:00 nginx: worker process
使得旧的主进程重新fork旧版的worker

[root@host2 sbin]# kill -s QUIT `cat /var/run/nginx/nginx.pid`
[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1430      1  0 12:13 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1469   1430  0 12:23 ?        00:00:00 nginx: worker process
然后退出新版本的主和worker

已经升级完成,想要回滚,或者降级

[root@host2 sbin]# !ps
ps -ef |grep nginx |grep -v "grep"
root       1371      1  0 11:48 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1411   1371  0 12:06 ?        00:00:00 nginx: worker process
16版本在运行


[root@host2 sbin]# ll
total 11952
-rwxr-xr-x 1 root root 3825016 Aug 28 11:06 nginx
-rwxr-xr-x 1 root root 8410944 Aug 27 19:13 nginx.14
[root@host2 sbin]# mv nginx nginx.16
[root@host2 sbin]# mv nginx.14 nginx
[root@host2 sbin]# ll
total 11952
-rwxr-xr-x 1 root root 8410944 Aug 27 19:13 nginx
-rwxr-xr-x 1 root root 3825016 Aug 28 11:06 nginx.16
更换为14版本

[root@host2 sbin]# kill -USR2 `cat /var/run/nginx/nginx.pid`
[root@host2 sbin]# ll /var/run/nginx/
total 8
-rw-r--r-- 1 root root 5 Aug 28 12:13 nginx.pid
-rw-r--r-- 1 root root 5 Aug 28 11:48 nginx.pid.oldbin
发送USR2信号,重载主程序文件

[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1371      1  0 11:48 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1411   1371  0 12:06 ?        00:00:00 nginx: worker process
root       1430   1371  0 12:13 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1431   1430  0 12:13 ?        00:00:00 nginx: worker process
此时2版本,进程共存

[root@host2 sbin]# nginx -v
nginx version: nginx/1.14.2
[root@host2 sbin]# kill -QUIT `cat /var/run/nginx/nginx.pid.oldbin`
退出16版本的进程

[root@host2 sbin]# ps -ef |grep nginx |grep -v "grep"
root       1430      1  0 12:13 ?        00:00:00 nginx: master process /usr/local/nginx-1.14/sbin/nginx
nginx      1431   1430  0 12:13 ?        00:00:00 nginx: worker process
此时只有14版本进程;完成降级/回滚;

reference

https://www.cnblogs.com/f-ck-need-u/p/7658111.html

updatedupdated2020-10-192020-10-19
加载评论