Nginx平滑升级和回滚
Posted y_zilong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx平滑升级和回滚相关的知识,希望对你有一定的参考价值。
nginx-1.18 编译安装
#安装编译工具和所需的依赖包
[root@yzl ~]# yum install -y wget gcc gcc-c++ zilb zlib-devel openssl openssl-devel pcre pcre-devel
#下载nginx tar包到/usr/local/src/
[root@yzl ~]# wget http://nginx.org/download/nginx-1.18.0.tar.gz -P /usr/local/src/
#解压
[root@yzl ~]# cd /usr/local/src/
[root@yzl src]# tar -xvf nginx-1.18.0.tar.gz
#创建用户数据目录并授权
[root@yzl ~]# mkdir -p /apps/nginx
[root@yzl ~]# useradd -s /sbin/nologin nginx
[root@yzl ~]# chown -R nginx.nginx /apps/nginx
#编译安装
[root@yzl ~]# cd /usr/local/src/nginx-1.18.0
[root@yzl nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
[root@yzl nginx-1.18.0]# make -j 4
[root@yzl nginx-1.18.0]# make install
#配置环境变量
[root@yzl ~]# ln -s /apps/nginx/sbin/nginx /usr/bin/
[root@yzl ~]# nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@yzl ~]#
#永久生效
[root@yzl ~]# vi /etc/profile.d/nginx.sh
[root@yzl ~]# source /etc/profile.d/nginx.sh
#开机启动配置文件
[root@yzl ~]# cat /etc/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /apps/nginx/logs/nginx.pid)"
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /apps/nginx/logs/nginx.pid)"
[Install]
WantedBy=multi-user.target
[root@yzl ~]#
平滑升级和回滚
原理:
1、将旧Nginx二进制文件换成新的Nginx程序文件(注意先备份)
2、向master进程发送USR2信号
3、master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin
4、master进程用新的Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx,主进程共同提供web服务,当前新的请求仍然由旧的Nginx的worker进程进行处理,将新生成的master进程的pid存放至新生成的pid文件nginx.pid
5、向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止
6、向旧master进程发送QUIT信号,关闭老master,并删除Nginx.pid.oldbin文件
7、如果发现升级有问题,可以回滚:向老master发送HUP,向新master发送QUIT
信号说明:
立即停止服务:stop,相当于信号SIGTERM,SIGINT
优雅的停止服务:quit,相当于信号SIGQUIT
平滑重启,重新加载配置文件:reload,相当于信号SIGHUP
重新开始记录日志文件:reopen,相当于信号SIGUSER1,在切割日志时用途较大
平滑升级可执行程序:发送信号SIGUSER2,在升级版本时使用
优雅的停止工作进程:发送信号SIGWINCH,在升级版本时使用
[root@yzl ~]# cd /usr/local/src/nginx-1.18.0/
[root@yzl nginx-1.18.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src
[root@yzl nginx-1.18.0]# man man/nginx.8
[root@yzl nginx-1.18.0]#
-s signal Send a signal to the master process. The argument signal can be one of: stop, quit, reopen, reload.
The following table shows the corresponding system signals:
stop SIGTERM
quit SIGQUIT
reopen SIGUSR1
reload SIGHUP
SIGINT, SIGTERM Shut down quickly.
SIGHUP Reload configuration, start the new worker process with a new configuration, and gracefully shut
down old worker processes.
SIGQUIT Shut down gracefully.
SIGUSR1 Reopen log files.
SIGUSR2 Upgrade the nginx executable on the fly.
SIGWINCH Shut down worker processes gracefully.
#下载最新稳定版
[root@yzl ~]# wget http://nginx.org/download/nginx-1.20.1.tar.gz -P /usr/local/src/
[root@yzl src]# tar -xvf nginx-1.20.1.tar.gz
#查看当前使用的版本及编译选项。结果如下:
[root@yzl nginx-1.20.1]#
[root@yzl nginx-1.20.1]# nginx -V
nginx version: nginx/1.18.0
built by gcc 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC)
built with OpenSSL 1.1.1g FIPS 21 Apr 2020
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
#configure arguments后面是以前编译时的参数,现在编译使用一样的参数
[root@yzl nginx-1.20.1]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
#只要make无需make install
[root@yzl nginx-1.20.1]# make -j 4
[root@yzl nginx-1.20.1]# objs/nginx -v
nginx version: nginx/1.20.1
[root@yzl nginx-1.20.1]#
#查看两个版本
[root@yzl nginx-1.20.1]# ll objs/nginx /apps/nginx/sbin/nginx
-rwxr-xr-x 1 root root 5837360 Jun 7 07:56 /apps/nginx/sbin/nginx
-rwxr-xr-x 1 root root 5926320 Jun 7 09:18 objs/nginx
[root@yzl nginx-1.20.1]#
#把之前的旧版的nginx命令备份
[root@yzl nginx-1.20.1]# mv /apps/nginx/sbin/nginx /apps/nginx/sbin/nginx.old
#把新版本的nginx命令复制过去
[root@yzl nginx-1.20.1]# cp ./objs/nginx /apps/nginx/sbin/
#检查一下有没有问题
[root@yzl nginx-1.20.1]# /apps/nginx/sbin/nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@yzl nginx-1.20.1]# ps aux |grep nginx
root 35855 0.0 0.0 42352 3364 ? Ss 08:47 0:00 nginx: master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
nginx 35866 0.0 0.1 77068 5276 ? S 08:48 0:00 nginx: worker process
root 38718 0.0 0.0 12132 1196 pts/4 S+ 09:43 0:00 grep --color=auto nginx
#USR2 平滑升级可执行程序,将存储有旧版本主进程ID的文件重命名为nginx.pid.oldbin,跟着启动新的nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的nginx进程,此时老的进程不会自动退出,但是当接收新的请求不作处理而是交给新的进程处理
[root@yzl nginx-1.20.1]# kill -USR2 `cat /apps/nginx/logs/nginx.pid`
[root@yzl nginx-1.20.1]# ps auxf |grep nginx
root 38724 0.0 0.0 12132 1196 pts/4 S+ 09:45 0:00 | \\_ grep --color=auto nginx
root 35855 0.0 0.0 42352 3364 ? Ss 08:47 0:00 nginx: master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
nginx 35866 0.0 0.1 77068 5276 ? S 08:48 0:00 \\_ nginx: worker process
root 38721 0.0 0.1 42240 5560 ? S 09:44 0:00 \\_ nginx: master process /apps/nginx/sbinnginx -c /apps/nginx/conf/nginx.conf
nginx 38722 0.0 0.1 76988 5104 ? S 09:44 0:00 \\_ nginx: worker process
[root@yzl nginx-1.20.1]#
[root@yzl nginx-1.20.1]# pstree -p
├─nginx(35855)─┬─nginx(38721)───nginx(38722)
│ └─nginx(35866)
[root@yzl nginx-1.20.1]# lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 35855 root 8u IPv4 109084 0t0 TCP *:http (LISTEN)
nginx 35866 nginx 8u IPv4 109084 0t0 TCP *:http (LISTEN)
nginx 38721 root 8u IPv4 109084 0t0 TCP *:http (LISTEN)
nginx 38722 nginx 8u IPv4 109084 0t0 TCP *:http (LISTEN)
[root@yzl nginx-1.20.1]#mv /apps/nginx/logs/nginx.pid /apps/nginx/logs/nginx.pid.oldbin
#先关闭旧的nginx的worker进程,而不关闭nginx主进程方便回滚
#向原nginx主进程发送WINCH信号,它会逐步关闭旗下的工作进程(主进程不退回),这时所有请求都会由新版nginx处理
[root@yzl nginx-1.20.1]# kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin`
[root@yzl nginx-1.20.1]# ps auxf |grep nginx
root 39044 0.0 0.0 12132 1120 pts/4 S+ 09:52 0:00 | \\_ grep --color=auto nginx
root 35855 0.0 0.0 42352 3364 ? Ss 08:47 0:00 nginx: master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
root 38721 0.0 0.1 42240 5560 ? S 09:44 0:00 \\_ nginx: master process /apps/nginx/sbinnginx -c /apps/nginx/conf/nginx.conf
nginx 38722 0.0 0.1 76988 5104 ? S 09:44 0:00 \\_ nginx: worker process
[root@yzl nginx-1.20.1]#
[root@yzl nginx-1.20.1]# pstree -p |grep nginx
|-nginx(35855)---nginx(38721)---nginx(38722)
[root@yzl nginx-1.20.1]#
#经过一段时间测试,新版本服务没问题,最后退出老的master
[root@yzl nginx-1.20.1]# kill -QUIT `cat /apps/nginx/logs/nginx.pid.oldbin`
#查看版本是不是已经新版了
[root@yzl nginx-1.20.1]# nginx -v
nginx version: nginx/1.20.1
[root@yzl nginx-1.20.1]# curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.20.1
Date: Mon, 07 Jun 2021 13:56:00 GMT
Content-Type: text/html
Content-Length: 6
Last-Modified: Mon, 07 Jun 2021 13:34:15 GMT
Connection: keep-alive
ETag: "60be2057-6"
Accept-Ranges: bytes
#让日志新文件生效
[root@yzl nginx-1.20.1]#kill -USER1 `cat /apps/nginx/logs/nginx.pid.oldbin`
#回滚
#如果升级的版本发现问题需要回滚,可以重新拉起旧版本的worker
注意:回滚的前提是不能关闭老版的master
[root@yzl nginx-1.20.1]# kill -HUP `cat /apps/nginx/logs/nginx.pid.oldbin`
[root@yzl nginx-1.20.1]# kill -QUIT `cat /apps/nginx/logs/nginx.pid`
以上是关于Nginx平滑升级和回滚的主要内容,如果未能解决你的问题,请参考以下文章