所谓的热升级也叫做热部署,或者平滑升级,也就是说,在不停止nginx服务的情况下,完成nginx的升级工作。
但是这里有一个注意点,就是使用这种方法有一个前提,前提就是你在启动nginx时使用的是nginx二进制文件的绝对路径,而不是直接在命令行中输入"nginx"的方式启动的nginx服务,不通过绝对路径启动的方式通常是为了方便,配置了nginx相关的环境变量,如果没有通过绝对路径启动nginx,那么当你向nginx进程发送更新的信号时,nginx进程可能会无法找到新的二进制程序(由于没有找新版本的二进制程序,所以没有任何反应)。
实验准备:
两个版本的nginx
[root@server3 ~]# ls
nginx-1.16.1.tar.gz nginx-1.17.8.tar.gz
安装旧版本:
tar zxf nginx-1.16.1.tar.gz
cd nginx-1.16.1
yum install gcc openssl-devel pcre-devel -y
./configure --prefix=/usr/local/nginx
make && make install
假设nginx正在提供服务,一切正常,现在我们想要对nginx进行热升级,大致步骤如下:
0、最重要的一步,备份。
[root@server3 nginx-1.16.1]# cd /usr/local/nginx/sbin/
[root@server3 sbin]# ls
nginx
[root@server3 sbin]# ./nginx #启动nginx
[root@server3 sbin]# netstat -antlupe | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 21348 4709/nginx: master
[root@server3 sbin]# ./nginx -v #查看安装ngixn的版本
nginx version: nginx/1.16.1
[root@server3 sbin]# ls
nginx
[root@server3 sbin]# cp nginx nginx.old #将其备份为nginx.old
[root@server3 sbin]# ls
nginx nginx.old
1、编译新版本
下载新版本的nginx,根据老版本的编译选项,对新版本完成编译的步骤,只对新版本进行编译操作,不执行安装操作,换句话说就是,只执行make命令,不执行make install命令,完成编译操作后,即可获取到我们需要的新版本的二进制文件。
使用nginx -V命令查看老版本的编译选项,新版本编译时需要使用这些选项,这里由于安装老版本时没有安装选项,故忽略此步。
[root@server3 ~]# tar zxf nginx-1.17.8.tar.gz #解压新版安装包
[root@server3 ~]# ls
gd-devel-2.0.35-26.el7.x86_64.rpm nginx-1.16.1.tar.gz nginx-1.17.8.tar.gz
nginx-1.16.1 nginx-1.17.8
[root@server3 ~]# cd nginx-1.17.8
[root@server3 nginx-1.17.8]# ls
auto CHANGES.ru configure html man src
CHANGES conf contrib LICENSE README
[root@server3 nginx-1.17.8]# ./configure --prefix=/usr/local/nginx #编译
[root@server3 nginx-1.17.8]# make
2、使用编译好的新版本的nginx二进制文件替换老版本的nginx二进制文件
确定已经备份老版本的nginx二进制文件,以防万一,用编译好的新版本的nginx二进制文件替换老版本的nginx二进制文件,此时老版本的nginx仍然在内存中正常运行,所以不用担心,我们替换的只是硬盘中的二进制文件,做好备份即可。
[root@server3 nginx-1.17.8]# cd /usr/local/nginx/sbin/
[root@server3 sbin]# ls
nginx nginx.old
[root@server3 sbin]# cp -f ~/nginx-1.17.8/objs/nginx .
cp: overwrite ‘./nginx’? y
3、对nginx的master进程(正在运行的老版本的master进程)发送USR2信号
对nginx的master进程(正在运行的老版本的master进程)发送USR2信号,老版本的master进程收到信号后,会通过新版本的二进制文件启动新版本的master进程,新版本的master进程会启动新版本的worker进程,此时新老版本的nginx进程同时存在。
[root@server3 sbin]# ps -ef | grep nginx | grep -v grep
root 4709 1 0 23:28 ? 00:00:00 nginx: master process ./nginx
nobody 4710 4709 0 23:28 ? 00:00:00 nginx: worker process
[root@server3 sbin]# kill -USR2 4709 #4709为老版本master进程的4709
[root@server3 sbin]# ps -ef | grep nginx | grep -v grep
root 4709 1 0 23:28 ? 00:00:00 nginx: master process ./nginx #老版本
nobody 4710 4709 0 23:28 ? 00:00:00 nginx: worker process #老版本
root 7258 4709 0 23:44 ? 00:00:00 nginx: master process ./nginx #新版本
nobody 7259 7258 0 23:44 ? 00:00:00 nginx: worker process #新版本
4、向老版本的master进程发送WINCH信号
向老版本的master进程发送WINCH信号,以便先优雅的停止老版本的worker进程,新的请求会被新版本的worker进程处理,此时老的master进程仍然存在,留下老的master进程是为了以防万一,以便随时回滚,此时老版本的master进程、新版本的master进程和新版本的worker进程同时存在,升级过程暂且完毕。
[root@server3 sbin]# kill -WINCH 4709
[root@server3 sbin]# ps -ef | grep nginx | grep -v grep
root 4709 1 0 23:28 ? 00:00:00 nginx: master process ./nginx #老版本
root 7258 4709 0 23:44 ? 00:00:00 nginx: master process ./nginx #新版本
nobody 7259 7258 0 23:44 ? 00:00:00 nginx: worker process #新版本
此时查看版本:
[root@server3 sbin]# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.17.8 #成功更新到新版本
5、平滑回退
如果升级后万一出现问题,则可以随时进行回滚,由于老版本的master进程并未停止,所以我们可以向老的master进程发送HUP信号,即可通过老版本的master进程重新生成老版本的worker进程,当老版本的worker进程重新被拉起后,即可向新版本的master进程发送USR2信号,使新版本的master进程解散其worker进程,之后再向新版本的master进程发送WINCH信号使旧版本的master进程接替新版本的master进程的工作,此时已经成功回退到旧版本。
[root@server3 sbin]# kill -HUP 4709 #通过老版本的master进程重新生成老版本的worker进程
[root@server3 sbin]# ps -ef | grep nginx | grep -v grep
root 4709 1 0 Feb26 ? 00:00:00 nginx: master process ./nginx #老版本
root 7258 4709 0 Feb26 ? 00:00:00 nginx: master process ./nginx #新版本
nobody 7259 7258 0 Feb26 ? 00:00:00 nginx: worker process #新版本
nobody 7291 4709 0 00:10 ? 00:00:00 nginx: worker process #老版本
[root@server3 sbin]# kill -USR2 7258 #7258为新版本master进程pid
[root@server3 sbin]# ps -ef | grep nginx | grep -v grep
root 4709 1 0 Feb26 ? 00:00:00 nginx: master process ./nginx
root 7258 4709 0 Feb26 ? 00:00:00 nginx: master process ./nginx
nobody 7259 7258 0 Feb26 ? 00:00:00 nginx: worker process
nobody 7291 4709 0 00:10 ? 00:00:00 nginx: worker process
[root@server3 sbin]# kill -WINCH 7258
[root@server3 sbin]# ps -ef | grep nginx | grep -v grep
root 4709 1 0 Feb26 ? 00:00:00 nginx: master process ./nginx
root 7258 4709 0 Feb26 ? 00:00:00 nginx: master process ./nginx
nobody 7291 4709 0 00:10 ? 00:00:00 nginx: worker process
[root@server3 sbin]# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.16.1 #成功回退到旧版本