NGINX热升级与恢复

热升级编译安装的nginx时,会用到USR2信号和WINCH信号

USR2:热升级nginx程序           WINCH:优雅的关闭相应的worker进程

所谓的热升级也叫做热部署,或者平滑升级,也就是说,在不停止nginx服务的情况下,完成nginx的升级工作。

但是这里有一个注意点,就是使用这种方法有一个前提,前提就是你在启动nginx时使用的是nginx二进制文件的绝对路径,而不是直接在命令行中输入"nginx"的方式启动的nginx服务,不通过绝对路径启动的方式通常是为了方便,配置了nginx相关的环境变量,如果没有通过绝对路径启动nginx,那么当你向nginx进程发送更新的信号时,nginx进程可能会无法找到新的二进制程序(由于没有找新版本的二进制程序,所以没有任何反应),有可能会在更新时,在日志中会发现错误,此处为了能够正常的演示整个过程,使用nginx二进制文件的绝对路径运行启动命令.

对nginx进行热升级,大致步骤如下

1、最重要的一步,备份。

2、下载新版本的nginx,根据老版本的编译选项,对新版本完成编译的步骤,只对新版本进行编译操作,不执行安装操作,换句话说就是,只执行make命令,不执行make install命令,完成编译操作后,即可获取到我们需要的新版本的二进制文件,之后,我们需要根据实际情况判断哪些文件需要被替换,此处描述的"根据情况判断"在后文中会有解释,先不用纠结,此处假设,根据情况判断后,只需要替换nginx二进制文件。

3、确定已经备份老版本的nginx二进制文件,以防万一,用编译好的新版本的nginx二进制文件替换老版本的nginx二进制文件,此时老版本的nginx仍然在内存中正常运行,所以不用担心,我们替换的只是硬盘中的二进制文件,做好备份即可。

4、对nginx的master进程(正在运行的老版本的master进程)发送USR2信号,老版本的master进程收到信号后,会通过新版本的二进制文件启动新版本的master进程,新版本的master进程会启动新版本的worker进程,此时新老版本的nginx进程同时存在。

5、向老版本的master进程发送WINCH信号,以便先优雅的停止老版本的worker进程,新的请求会被新版本的worker进程处理,此时老的master进程仍然存在,留下老的master进程是为了以防万一,以便随时回滚,此时老版本的master进程、新版本的master进程和新版本的worker进程同时存在,升级过程暂且完毕。

6、如果升级后万一出现问题,则可以随时进行回滚,由于老版本的master进程并未停止,所以我们可以向老的master进程发送HUP信号,即可通过老版本的master进程重新生成老版本的worker进程,当老版本的worker进程重新被拉起后,即可向新版本的master进程发送QUIT信号,以便优雅的关闭新版本的nginx进程,回滚操作完毕。

备份

[root@myserver_3 sbin]# ls
nginx  nginx.old
[root@myserver_3 sbin]# 

我想要热升级nginx,于是,我下载了当前的新版本,新版本的版本号为1.16.1

[root@myserver_3 ~]# wget  http://nginx.org/download/nginx-1.16.1.tar.gz
--2021-01-10 00:43:57--  http://nginx.org/download/nginx-1.16.1.tar.gz
Resolving nginx.org (nginx.org)... 3.125.197.172, 52.58.199.22, 2a05:d014:edb:5704::6, ...
Connecting to nginx.org (nginx.org)|3.125.197.172|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1032630 (1008K) [application/octet-stream]
Saving to: ‘nginx-1.16.1.tar.gz’

100%[=======================================>] 1,032,630    530KB/s   in 1.9s   

2021-01-10 00:43:59 (530 KB/s) - ‘nginx-1.16.1.tar.gz’ saved [1032630/1032630]

[root@myserver_3 ~]# 

查看编译信息

[root@myserver_3 sbin]# /nginx/sbin/nginx  -V
nginx version: nginx/1.14.2
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=/nginx --with-file-aio --with-http_auth_request_module --with-http_ssl_module --with-http_v2_module

configure命令使用的编译选项就是旧版本中使用的选项

[root@myserver_3 nginx-1.16.1]# pwd
/root/nginx-1.16.1
[root@myserver_3 nginx-1.16.1]# ls
auto     CHANGES.ru  configure  html     man     src
CHANGES  conf        contrib    LICENSE  README
[root@myserver_3 nginx-1.16.1]# ./configure --prefix=/nginx --with-file-aio --with-http_auth_request_module --with-http_ssl_module --with-http_v2_module

make编译

[root@myserver_2 nginx-1.16.1]# make
make -f objs/Makefile
make[1]: Entering directory `/root/nginx-1.16.1'
cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g  -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
	-o objs/src/core/nginx.o \
	src/core/nginx.c

注意:此处只进行编译步骤,不执行安装步骤,也就是说,只执行"make"命令,不执行"make install"命令,因为"make install"命令的本质就是将编译好的文件复制到对应的目录中,所以此处省略"make install"命令,以防止某些老的配置文件被覆盖,因为只是为了升级nginx,原来的配置仍然需要保持不变,所以要确保配置文件不会被覆盖。

完成上述步骤后,新版本的nginx二进制文件已经编译完成了,现在我们要做的就是使用新版本的二进制程序替换掉老版本的二进制程序,新版本的二进制文件生成在编译目录的objs目录中,即objs/nginx文件

[root@myserver_3 objs]# pwd
/root/nginx-1.16.1/objs
[root@myserver_3 objs]# ls
autoconf.err  nginx    ngx_auto_config.h   ngx_modules.c  src
Makefile      nginx.8  ngx_auto_headers.h  ngx_modules.o
[root@myserver_3 objs]# 
[root@myserver_3 objs]# pwd
/root/nginx/nginx-1.16.1/objs
[root@myserver_3 objs]# ls
autoconf.err  nginx    ngx_auto_config.h   ngx_modules.c  src
Makefile      nginx.8  ngx_auto_headers.h  ngx_modules.o
[root@myserver_3 objs]# cp -f nginx /nginx/sbin/nginx
cp: overwrite ‘/nginx/sbin/nginx’? y

虽然我们使用新的文件替换了旧版本的文件,但是我们并没有运行这些文件,也就是说,现在在内存中运行的nginx进程,仍然是老版本的nginx,查看一下当前运行的nginx进程

[root@myserver_3 objs]# ps -ef|grep nginx
root      31998      1  0 11:44 ?        00:00:00 nginx: master process /nginx/sbin/nginx
nobody    31999  31998  0 11:44 ?        00:00:00 nginx: worker process
root      32008   7679  0 11:44 pts/3    00:00:00 grep --color=auto nginx

当前nginx进程的主进程号是31988,也就是说,老版本的nginx的master进程的PID是31988,而且从老版本的master进程信息中可以看到,我使用的启动命令是" /nginx/sbin/nginx",这是一个绝对路径命令

此时不要使用nginx -v命令查看nginx版本, 因为nginx二进制文件已经替换成了1.16.1版本的nginx二进制文件,所以,如果此时使用nginx -v命令查看版本,得到的版本号必定是1.16.1,但是实际上,内存中运行的nginx进程版本仍然是1.14.2,如果你想要确定此刻内存中真正工作的nginx进程的版本号,可以故意访问一个不存在的资源,默认情况下,nginx的404页面中会显示nginx进程的版本号(除非你修改了相关设置),如下图所示,我故意访问了一个不存在的资源,可以看出,当前内存中的nginx版本号仍然是1.14.2

[root@myserver_3 sbin]# /nginx/sbin/nginx -v
nginx version: nginx/1.16.1
[root@myserver_3 sbin]# 

现在,我们来搞清楚一下状况,我们已经使用新版本的文件替换了老版本的文件,但是我们并没有运行新版本的程序,内存中的nginx进程仍然是老版本的nginx进程,所以,我们需要使用新版本的程序启动新的进程,此时,就需要用到USR2信号了,此刻,我们只需要向老版本的nginx的master进程发送USR2信号,老master进程就会使用新版本的二进制文件来启动新的master进程,示例如下:

向老版本master进程发送USR2信号

 kill -USR2 31988

老版本master进程收到USR2信号后,会根据老版本master进程中的nginx启动路径(绝对路径),启动一个新的master进程,由于nginx二进制文件已经替换为新版本的二进制文件,所以,新启动的nginx进程就是新版本的

[root@myserver_3 sbin]# kill -USR2 31998
[root@myserver_3 sbin]# ps -ef|grep nginx
root      31998      1  0 11:44 ?        00:00:00 nginx: master process /nginx/sbin/nginx
nobody    31999  31998  0 11:44 ?        00:00:00 nginx: worker process
root      32123  31998  0 11:46 ?        00:00:00 nginx: master process /nginx/sbin/nginx
nobody    32124  32123  0 11:46 ?        00:00:00 nginx: worker process
root      32128   7679  0 11:46 pts/3    00:00:00 grep --color=auto nginx

如上述信息所示,此时新老版本的nginx进程同时存在,老版本的master进程的PID为31988,老版本的worker进程的PID为31989,新版本的master进程的PID为32123,它的父进程的PID为31988,也就是说,这个新版本的master进程是由老版本的master进程启动的,新版本的worker进程的PID是32124,它是由新版本的master进程生成的。

此时,新老版本的nginx进程同时存在,但是我们的最终目的是使用新版本的nignx提供服务,于是,我们需要先优雅的停止老版本的worker进程,此时就需要用到"WINCH"信号了,当老版本的master进程接收到"WINCH"信号后,会停止老版本的worker进程,但是老版本的master进程并不会停止,我们留下老版本的master进程是为了以防万一,具体操作如下

[root@myserver_3 sbin]# kill -WINCH 31998
[root@myserver_3 sbin]# ps -ef|grep nginx
root      31998      1  0 11:44 ?        00:00:00 nginx: master process /nginx/sbin/nginx
root      32123  31998  0 11:46 ?        00:00:00 nginx: master process /nginx/sbin/nginx
nobody    32124  32123  0 11:46 ?        00:00:00 nginx: worker process
root      32189   7679  0 11:47 pts/3    00:00:00 grep --color=auto nginx
[root@myserver_3 sbin]# 

老版本的worker进程已经优雅的停止了(优雅的停止是在处理完当前连接的请求后再行停止),但是老版本的master进程还在,此时,再次故意访问一个不存在的资源,会发现nginx的版本号已经发生了改变,升级完成。

如果出问题可回滚操作:

当我们向老版本的master进程发送HUP信号后,老版本的master进程启动了一个老版本的worker进程,PID为31988,老版本的worker进程启动后,我们向新版本的master进程发送了QUIT信号,以便优雅的停止新版本的nginx进程,新版本的nginx进程停止后,再次查看nginx进程,只剩下老版本的nginx进程了,此时,回滚完成

[root@myserver_3 sbin]# kill -HUP 31998
[root@myserver_3 sbin]# ps -ef|grep nginx
root      31998      1  0 11:44 ?        00:00:00 nginx: master process /nginx/sbin/nginx
root      32123  31998  0 11:46 ?        00:00:00 nginx: master process /nginx/sbin/nginx
nobody    32124  32123  0 11:46 ?        00:00:00 nginx: worker process
nobody    32254  31998  0 11:48 ?        00:00:00 nginx: worker process
root      32257   7679  0 11:48 pts/3    00:00:00 grep --color=auto nginx
[root@myserver_3 sbin]# kill -QUIT 32123
[root@myserver_3 sbin]# ps -ef|grep nginx
root      31998      1  0 11:44 ?        00:00:00 nginx: master process /nginx/sbin/nginx
nobody    32254  31998  0 11:48 ?        00:00:00 nginx: worker process
root      32323   7679  0 11:49 pts/3    00:00:00 grep --color=auto nginx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值