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