nginx平滑升级、nginx支持的kill信号

  • Post author:
  • Post category:其他




前言

环境:

centos7.9、源码编译安装的nginx



nginx支持的kill信号

我们源码编译安装的

nginx

,通过直接执行

/usr/local/nginx/sbin/nginx

来启动

nginx

,其中停止,退出,重开日志,重载配置是通过

/usr/local/nginx/sbin/nginx -s stop|quit|reopen|reload

来发送信息给

master

进程实现的。除了这种方式,官方说明文档显示还提供

kill

命令来发送对应的信号给

nginx

主进程,

nginx



master

进程接收到这些信号就会执行对应的操作,如下:

kill 命令传送信号给nginx的master进程,注意是发送给master进程,不是worker进程:
TERM、INIT  :强制退出,当前的请求不执行完成就退出 等介于 ./nginx -s stop 
QUIT 		:优雅退出,等待请求执行完成后退出 等介于 ./nginx -s quit
HUP			:重载配置文件,用新的配置文件启动新的work进程并优雅的关闭旧的work进程,等介于./nginx -s reload
USR1		:重开日志,等价于./nginx -s reopen
USR2		:平滑的升级nginx,拉起一个新的nginx主进程,同时做到不停止旧的nginx主进程
WINCH		:优雅的关闭worker进程,发送一个WINCH信号给master进程,告知其优雅的关闭worker进程

演示示例:
kill -TERM 195916			#强制停止nginx,等价于 ./nginx -s stop
kill -INT 197019			#强制停止nginx,等价于 ./nginx -s stop 
kill -QUIT 197073			#优雅的退出nginx,等价于 ./nginx -s quit 
kill -HUP 197075			#重载配置文件,等价于 ./nginx -s reload 
kill -USR1 197220			#重开日志,等价于 ./nginx -s reopen 
kill -WINCH 197222			#优雅的关闭worker进程

备注:信号都是发送给nginx的master进程的



先安装一个nginx-1.18.0旧版本来演示

useradd -s /sbin/nologin -M nginx
yum -y install gcc gcc-c++ make pcre pcre-devel zlib-devel zlib openssl-devel openss
wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar zxvf nginx-1.18.0.tar.gz
cd nginx-1.18.0
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module  --with-http_ssl_modul
make -j 8
make install
cd usr/local/nginx/sbin
./nginx
ps -ef | grep nginx
root      1679     1  0 11:23 ?        00:00:00 nginx: master process ./nginx
nginx     1680  1679  0 11:23 ?        00:00:00 nginx: worker process
nginx     1681  1679  0 11:23 ?        00:00:00 nginx: worker process
#下面开始平滑升级nginx为nginx-1.22.0版本,不停nginx升级,实现平滑升级nginx



方法一、 nginx平滑升级

1、如果我们想要更换

nginx

版本,升级为更高版本的

nginx

,无非就是重新编译安装新版本的

nginx

,然后停止旧版本

nginx

,启动新版本

nginx

。这切换期间势必存在

nginx

服务不可用。(因为我们不能同时启动两个版本的

nginx

,会存在端口冲突的问题)

2、官网给我们提供了上面问题的解决方案,即平滑升级

nginx

,所谓平滑升级是指旧的

nginx

不停止,新的

nginx

又可以启动,即同时存在旧的

nginx

和新的

nginx

,当旧的

nginx

请求处理完毕,关闭旧的

nginx

。这就要用到我们前面所说的

USR2

信号来实现

nginx

的平滑升级了。

USR2 	平滑启动nginx进程
WINCH	优雅的停止worker进程
QUIT	优雅的停止旧的master进程	

先查看现在的nginx的版本:

/usr/local/nginx/sbin/nginx -V
ginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module

编译安装高版本的

nginx

,编译参数要与原来旧版本参数的一致(只多不少),安装路径要与原来旧版本安装路径一样;

注意:升级新版本,新版本的安装路径要与旧版本的安装路径保持一致,安装完成,会在

sbin

目录下存在一个

nginx(新版本)、nginx.old(旧版本)

wget http://nginx.org/download/nginx-1.22.0.tar.gz
tar -zxvf nginx-1.22.0.tar.gz
cd nginx-1.22.0
./configure  --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module

make -j 8 && make install 
[root@nginx ~]# cd /usr/local/nginx/sbin	#进入nginx的目录
[root@nginx sbin]# ll						#查看nginx的可执行文件,可以看到我们现在有两个nginx的可执行文件
total 11712
-rwxr-xr-x 1 root root 6034160 Sep 23 12:47 nginx		#新版本的nginx-1.22.0
-rwxr-xr-x 1 root root 5952184 Sep 23 11:22 nginx.old	#原来旧版本nginx-1.18.0被备份为nginx.old了
[root@nginx sbin]# ./nginx -V				#查看nginx的版本,确认是新版本的nginx-1.22.0
nginx version: nginx/1.22.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
[root@nginx sbin]# ./nginx.old -V			#查看nginx的版本,确认是旧版本的nginx-1.18.0
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
[root@nginx sbin]#

这时候直接

./nginx

启动新版本肯定是报错的,因为端口被占用,我们需要使用

USR2

来平滑升级

nginx

#先查看旧版本的nginx的进程
[root@nginx sbin]# ps -ef | grep nginx
root      1679     1  0 11:23 ?        00:00:00 nginx: master process ./nginx	#记住旧版本的nginx的master进程pid
nginx     1851  1679  0 11:25 ?        00:00:00 nginx: worker process
nginx     1852  1679  0 11:25 ?        00:00:00 nginx: worker process
[root@nginx sbin]#

#使用 kill -USR2 旧的主进程号 命令来平滑升级
[root@nginx sbin]# kill -USR2 1679	#向旧版本nginx的master进程发送USR2信号

#再查看nginx的进程,这时就启动新版本的nginx进程,此时同时存在新旧版本的nginx进程
[root@nginx sbin]# ps -ef | grep nginx
root      1679     1  0 11:23 ?        00:00:00 nginx: master process ./nginx	#这是旧版本的nginx/1.18.0
nginx     1851  1679  0 11:25 ?        00:00:00 nginx: worker process			#这是旧版本的nginx/1.18.0
nginx     1852  1679  0 11:25 ?        00:00:00 nginx: worker process			#这是旧版本的nginx/1.18.0

root      9336  1679  0 12:55 ?        00:00:00 nginx: master process ./nginx	#这是新版本的nginx/1.22.0
nginx     9337  9336  0 12:55 ?        00:00:00 nginx: worker process			#这是新版本的nginx/1.22.0
nginx     9338  9336  0 12:55 ?        00:00:00 nginx: worker process			#这是新版本的nginx/1.22.0

#先使用 kill -WINCH 旧的主进程号 命令优雅的关闭旧版本的worker进程(等连接基本处理完毕了在关闭旧的worker进程也不迟)
[root@nginx sbin]# kill -WINCH 1679		#向旧版本nginx的master进程发送WINCH信号,告知其优雅的停止worker进程

#确认新版nginx升级没有问题了,再使用命令 kill -QUIT	 旧的主进程号 优雅的关闭旧版本的nginx master进程
[root@nginx sbin]# kill -QUIT 1679		#向旧版本nginx的master进程发送QUIT信号,告知其优雅的退出

#至此,此时已经完成了nginx版本的平滑升级



方法二、 nginx平滑升级

编译安装高版本的nginx:

wget http://nginx.org/download/nginx-1.22.0.tar.gz
tar -zxvf nginx-1.22.0.tar.gz
./configure  --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module

#预编译完成后会得到一个Makefile 文件,我们来看下这个文件的内容,如下:
[root@nginx nginx-1.22.0]# cat Makefile 

default:	build

clean:
	rm -rf Makefile objs

.PHONY:	default clean

build:
	$(MAKE) -f objs/Makefile

install:
	$(MAKE) -f objs/Makefile install

modules:
	$(MAKE) -f objs/Makefile modules

upgrade:
	/usr/local/nginx/sbin/nginx -t

	kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`				#平滑升级
	sleep 1
	test -f /usr/local/nginx/logs/nginx.pid.oldbin

	kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`			#优雅的关闭旧版本的nginx

.PHONY:	build install modules upgrade
[root@nginx nginx-1.22.0]# 

#如上看到的,make 命令有个参数upgrade,这个参数就是平滑升级的,看内容应该可以看到,其平滑升级的原理仍然是我们前面方法一的说的一样,先
#发送 USR2 信号给旧的nginx master进程告知其平滑升级,拉起新版本的nginx进程,然后再发送QUIT信号给旧版本的master进程,优雅的关闭旧版
#本的nginx。

[root@nginx sbin]#  make install  &&  make upgrade  			#直接平滑升级
[root@nginx sbin]# ll
total 11712
-rwxr-xr-x 1 root root 6034160 Sep 23 17:36 nginx				#新版本的nginx
-rwxr-xr-x 1 root root 5952184 Sep 23 17:27 nginx.old			#就版本的nginx
[root@nginx sbin]# 
[root@nginx sbin]# ps -ef | grep nginx							#现在只有新版本的nginx
root     31946     1  0 17:36 ?        00:00:00 nginx: master process ./nginx
nginx    31947 31946  0 17:36 ?        00:00:00 nginx: worker process
root     32137 15942  0 17:40 pts/4    00:00:00 grep --color=auto nginx
[root@nginx sbin]#
#至此,nginx平滑升级完成



方法三、 nginx平滑升级(保守方法)

同理,解压编译新版本的nginx,但此时的安装路径安装在一个全新的目录,不再与原来旧版本的安装路径一样。

wget http://nginx.org/download/nginx-1.22.0.tar.gz
tar -zxvf nginx-1.22.0.tar.gz
./configure  --prefix=/usr/local/nginx2 --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
make -j 8 && make install 											#安装全新版本的nginx
mv /usr/local/nginx/sbin/nginx  /usr/local/nginx/sbin/nginx.old		#备份原来的旧版本的nginx,备份不影响正在运行的nginx进程
cp /usr/local/nginx2/sbin/nginx /usr/local/nginx/sbin/ 				#将新版本的nginx可执行文件复制到旧版本的安装路径下

#同理,下面的步骤仍然是发送信号SER2给旧版本的nginx的master进程进行平滑升级nginx,然后再关闭旧版本的worker进程和master进程

[root@nginx sbin]# kill -USR2 1679		#向旧版本nginx的master进程发送USR2信号,让其拉起新版本的nginx

#先使用 kill -WINCH 旧的主进程号 命令优雅的关闭旧版本的worker进程
[root@nginx sbin]# kill -WINCH 1679		#向旧版本nginx的master进程发送WINCH信号,告知其优雅的停止worker进程

#确认nginx升级没有问题了,再使用命令 kill -QUIT	 旧的主进程号 优雅的关闭旧版本的nginx master进程
[root@nginx sbin]# kill -QUIT 1679		#向旧版本nginx的master进程发送QUIT信号,告知其优雅的退出

#至此,已经完成了nginx版本的平滑升级 



nginx版本回退

如果在使用新版本的

nginx

过程中发现新版本存在问题,那么可以进行

nginx

版本回退,回退到旧版本的

nginx

版本回退可以分2种情况,如下:

1、事前对旧版本

nginx

进行备份,若出现问题,直接将旧版本重新拷贝会

/usr/local

目录下,重启

nginx

旧版本操作,执行如下:

#停止nginx服务进行版本回退
killall nginx
cp /usr/local/nginx-1.18.0.bak  /usr/local/nginx
/usr/local/nginx/sbin/nginx
#检查nginx状态
ps -ef |grep nginx

2、在新版本

nginx



master

进程和旧版本的master进程同时存在时,即只关闭了旧版本的

worker

进程没有关闭旧版本的

master

进程的情况下,可以这样回滚,如下:

#向旧版本的master进程发送HUP信号,重载配置,会重新拉起新的worker进程
kill -HUP 旧masterPID				# HUP是重载配置,会重新启动worker进程

#关闭新版本nginx的master进程,并将原sbin目录下的nginx.old(旧版本nginx二进制文件)重新改回nginx,以便管理nginx
kill -WINCH 新master的PID			#优雅额关闭新版本的worker进程
kill -QUIT 新master的PID			#优雅额关闭新版本的matser进程
cd /usr/local/nginx/sbin/
mv nginx nginx_1.22.0_bak			#先备份新版本的nginx可执行文件
mv nginx.old nginx					#将旧版本的nginx可执行文件恢复回来



总结


nginx支持的kill发送以下的信号:

kill -TERM 195916			#强制停止nginx,等价于 ./nginx -s stop
kill -INT 197019			#强制停止nginx,等价于 ./nginx -s stop 
kill -QUIT 197073			#优雅的退出nginx,等价于 ./nginx -s quit 
kill -HUP 197075			#重载配置文件,等价于 ./nginx -s reload 
kill -USR1 197220			#重开日志,等价于 ./nginx -s reopen 
kill -USR2 197220			#平滑升级nginx
kill -WINCH 197222			#优雅的关闭worker进程
备注:信号都是发送给nginx的master进程的


平滑升级nginx的大概思路:

方法一、
1、编译安装高版本的nginx,其./configure预编译的参数要与原来旧版本的参数一致,包括安装路径也要一致;
2、make -j 10 && make install 编译安装;
3、安装完成之后,在/usr/local/nginx/sbin/目录下就会存在一个可执行文件,nginx、nginx.old,前者是新版本的可执行文件,后者是旧版本的可执行文件;
4、使用 kill -USR2 旧版本的masterPID   命令进行平滑升级,此时就会同时存在新版本旧版本的nginx进程;
5、使用 kill -WINCH 旧版本的masterPID  命令优雅的关闭旧版本的worker进程
6、确认新版本的nginx进程没有问题后,此时可以使用 kill -QUIT 旧版本的masterPID  命令优雅的关闭旧版本的master进程;
7、nginx升级已完成。
方法二、
1、编译安装高版本的nginx,其./configure预编译的参数要与原来旧版本的参数一致,包括安装路径也要一致;
2、make install && make upgrade  编译安装,make upgrade直接平滑升级;
3、安装完成之后,在/usr/local/nginx/sbin/目录下就会存在一个可执行文件,nginx、nginx.old,前者是新版本的可执行文件,后者是旧版本的可执行文件;
4、此时平滑升级完成了,ps -ef  | grep nginx 查看只会有新版本的nginx,因为当你执行make upgrade的时候,其实已经发送了kill -QUIT 信号给旧版本的nginx,所以旧版本的nginx进程已经优雅的退出了。
5、nginx升级已完成。
方法三、(保守方法)
1、解压编译新版本的nginx,但此时的安装路径安装在一个全新的目录,不再与原来旧版本的安装路径一样;
2、备份旧版本的可行性文件,复制新版本的nginx的可执行文件
mv /usr/local/nginx/sbin/nginx  /usr/local/nginx/sbin/nginx.old		#备份原来的旧版本的nginx,备份不影响正在运行的nginx进程
cp /usr/local/nginx2/sbin/nginx /usr/local/nginx/sbin/ 				#将新版本的nginx可执行文件复制到旧版本的安装路径下
3、使用 kill -USR2 旧版本的masterPID   命令进行平滑升级,此时就会同时存在新版本旧版本的nginx进程;
4、使用 kill -WINCH 旧版本的masterPID  命令优雅的关闭旧版本的worker进程
5、确认新版本的nginx进程没有问题后,此时可以使用 kill -QUIT 旧版本的masterPID  命令优雅的关闭旧版本的master进程;
6、nginx升级已完成。


版本回退:


1、如果事前对旧版本

nginx

进行备份,若出现问题,直接将旧版本重新拷贝会

/usr/local

目录下,重启

nginx

旧版本操作,执行如下:

#停止nginx服务进行版本回退
killall nginx
cp /usr/local/nginx-1.18.0.bak  /usr/local/nginx
/usr/local/nginx/sbin/nginx
#检查nginx状态
ps -ef |grep nginx

2、在新版本nginx的master进程和旧版本的master进程同时存在时,即只关闭了旧版本的worker进程没有关闭旧版本的master进程的情况下,可以这样回滚,如下:

#向旧版本的master进程发送HUP信号,重载配置,会重新拉起新的worker进程
kill -HUP 旧masterPID				# HUP是重载配置,会重新启动worker进程

#关闭新版本nginx的master进程,并将原sbin目录下的nginx.old(旧版本nginx二进制文件)重新改回nginx,以便管理nginx
kill -WINCH 新master的PID			#优雅额关闭新版本的worker进程
kill -QUIT 新master的PID				#优雅的关闭新版本的matser进程
cd /usr/local/nginx/sbin/
mv nginx nginx_1.22.0_bak			#先备份新版本的nginx可执行文件
mv nginx.old nginx					#将旧版本的nginx可执行文件恢复回来



版权声明:本文为MssGuo原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。