当前位置: 首页 > news >正文

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

前言

环境: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进程:
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进程
[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。

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,但此时的安装路径安装在一个全新的目录,不再与原来旧版本的安装路径一样。

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信号
#先使用 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可执行文件恢复回来

相关文章:

  • Golang中进行Url编码,再也不怕奇奇怪怪的参数格式了
  • Linux机器时钟同步
  • Go语言基础 指针 运算符
  • Elasticsearch部署和问题汇总
  • 如何搭建边缘计算盒子IVP02E环境部署?
  • 【Linux私房菜】第八期——面试
  • jest 使用 jest-allure 测试报告
  • navicat连接远程服务器报错代码:10038
  • 笔试题/面试题——WEB前端性能优化,提高页面加载速度
  • CNN-运动鞋品牌识别
  • 可行性研究的任务有哪些?可行性研究包括哪些步骤?
  • 数据湖技术之快速体验 Hudi
  • [Spring Boot 2]整合持久层技术
  • Mysql_存储过程
  • Maven(基础)
  • 【剑指offer】让抽象问题具体化
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • Android 控件背景颜色处理
  • HTTP中的ETag在移动客户端的应用
  • java 多线程基础, 我觉得还是有必要看看的
  • sessionStorage和localStorage
  • Spring核心 Bean的高级装配
  • v-if和v-for连用出现的问题
  • Vue.js 移动端适配之 vw 解决方案
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 动态魔术使用DBMS_SQL
  • 对超线程几个不同角度的解释
  • 多线程事务回滚
  • 简单易用的leetcode开发测试工具(npm)
  • 设计模式(12)迭代器模式(讲解+应用)
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 因为阿里,他们成了“杭漂”
  • 正则表达式
  • 转载:[译] 内容加速黑科技趣谈
  • mysql面试题分组并合并列
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 回归生活:清理微信公众号
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • $L^p$ 调和函数恒为零
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)shell调试方法
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • (转载)CentOS查看系统信息|CentOS查看命令
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Core 成都线下面基会拉开序幕
  • .net framework 4.0中如何 输出 form 的name属性。
  • .net wcf memory gates checking failed