引言:我们在世纪的生产环境中,基本上任何时刻都会有客户访问我们的nginx服务器(假定我们用的是nginx服务器)。那么如果我们预期要对nginx的版本进行更新,但是我们一定要注意的是我们决不能将nginx暂时关闭,然后升级后再启动,这样明显对于用户的体验要大打折扣,那么我们就要用到我们再应用中使用的平滑升级,即再不管比nginx服务的同时完成对nginx的更新
nginx平滑升级的基本思想:
- 在不停止老进程的情况下,启动新进程
- 老进程负责处理仍然没有处理完的请求,但不再接受处理请求
- 新进程接收新请求
- 老进程处理完所有请求,关闭所有连接后停止
实验:nginx的平滑升级
一,安装并启动一个版本的nginx进程,这里我们选择1.14版本的nginx
1.解压缩安装包
2.关闭debug日志
[root@server1 ~]# cd nginx-1.14.0/
[root@server1 nginx-1.14.0]# vim auto/cc/gcc
171 # debug
172 #CFLAGS="$CFLAGS -g"
3.下载nginx编译所需要的依赖
[root@server1 ~]# yum install pcre-devel zlib-devel gcc -y
4.编译
[root@server1 nginx-1.14.0]# ./configure --prefix=/usr/local/nginx --with-file-aio
5.编译安装
[root@server1 nginx-1.14.0]# make && make install
6.给配置文件增加高亮显示(方便我们修改配置文件,可以选择不做)
[root@server1 ~]# mkdir .vim
[root@server1 ~]# cp -r nginx-1.14.0/contrib/vim/* .vim/
[root@server1 ~]# vim /usr/local/nginx/conf/nginx.conf
7.测试配置文件正确性即版本号
[root@server1 ~]# cd /usr/local/nginx/sbin/
[root@server1 sbin]# ./nginx -t ##看看配置是否正确
[root@server1 sbin]# ./nginx -V ##查看nginx的版本号和所加的模块
8.修改配置文件
[root@server1 sbin]# vim /usr/local/nginx/conf/nginx.conf
1
2 user nginx nginx; ##设置用户和用户组为nginx
3 worker_processes auto; ##设置产生和cpu个数相同的进程来处理请求
4
5 #error_log logs/error.log;
6 #error_log logs/error.log notice;
7 #error_log logs/error.log info;
8
9 #pid logs/nginx.pid;
10
11
12 events {
13 worker_connections 65535; ##更改最大连接数
14 }
[root@server1 sbin]# useradd nginx
修改linux资源限制刚才设置的最大连接数,
[root@server1 sbin]# vim /etc/security/limits.conf
9.启动nginx
[root@server1 sbin]# ./nginx
[root@server1 sbin]# netstat -antlupe | grep nginx ##查看nginx的端口是否开启,即nginx是否开启
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 37655 14467/nginx: master
[root@server1 sbin]# ps ax | grep nginx ##查看nginx的进程,一定要记住下方的master进程的进程号,后面会用到
14467 ? Ss 0:00 nginx: master process ./nginx
14468 ? S 0:00 nginx: worker process
14472 pts/0 S+ 0:00 grep --color=auto nginx
二,nginx的平滑升级,这里我们将其升级至1.16版本
1.准备1.16的nginx版本
2.解压缩
3.测试其存在特性,编译
[root@server1 ~]# cd nginx-1.16.0/
[root@server1 nginx-1.16.0]# ./configure --prefix=/usr/local/nginx --with-file-aio #注意这里编译的参数一定要和之前的相同
[root@server1 nginx-1.16.0]# make ##注意这里千万不能make install ,否则就会覆盖和老版本相关的文件
4.查看新版本的二进制执行文件
5.备份老版本的而今值可执行文件,防止更新失败版本无法回退
6.复制新版本的执行文件到就版本的目录下
注意,此时的nginx的执行文件的版本就是我们要升级的新版本
7.查看系统进程
[root@server1 sbin]# ps ax | grep nginx
14467 ? Ss 0:00 nginx: master process ./nginx
14468 ? S 0:00 nginx: worker process
17071 pts/0 S+ 0:00 grep --color=auto nginx
注意对比,发现这个14467进程使我们之前的nginx进程
客户端查看此时生效的nginx服务器
8.在不停掉老版本进程的条件下,启动新进程
发现仍然是1.14版本在进行服务,这是因为现在的进程依旧是老进程
9.了解nginx相关的信号简介
主进程(master)
TERM, INT: 立刻退出
QUIT: 等待工作进程结束后再退出
KILL: 强制终止进程
HUP: 重新加载配置文件,使用新的配置启动工作进程,并逐步关闭旧进程。
USR1: 重新打开日志文件
USR2: 启动新的主进程,实现热升级
WINCH: 逐步关闭工作进程
工作进程(worker)
TERM, INT: 立刻退出
QUIT: 等待请求处理结束后再退出
USR1: 重新打开日志文件
10.在不停掉老进程的情况下,启动新进程
[root@server1 sbin]# kill -USR2 14467 ##让14467进程的工作进程不再接收新的请求,只处理当前的请求。同时打开新版本nginx的master进程和他的工作进程,处理新的请求
[root@server1 sbin]# ps -ef | grep nginx
root 14467 1 0 12:46 ? 00:00:00 nginx: master process ./nginx
nginx 14468 14467 0 12:46 ? 00:00:00 nginx: worker process
root 17078 14467 0 13:14 ? 00:00:00 nginx: master process ./nginx
nginx 17079 17078 0 13:14 ? 00:00:00 nginx: worker process
root 17081 2067 0 13:14 pts/0 00:00:00 grep --color=auto nginx
发现出现了新的nginx进程,它的进程号是17078
11.老进程处理完所有请求后,关闭所有连接,停止
[root@server1 sbin]# kill -WINCH 14467 ##关闭旧版本master的worker进程
[root@server1 sbin]# ps -ef | grep nginx
root 14467 1 0 12:46 ? 00:00:00 nginx: master process ./nginx
root 17078 14467 0 13:14 ? 00:00:00 nginx: master process ./nginx
nginx 17079 17078 0 13:14 ? 00:00:00 nginx: worker process
root 17084 2067 0 13:20 pts/0 00:00:00 grep --color=auto nginx
然后等待更新完毕后,关掉旧版本的master进程
[root@server1 sbin]# kill -9 14467
[root@server1 sbin]# ps -ef | grep nginx
root 17078 1 0 13:14 ? 00:00:00 nginx: master process ./nginx
nginx 17079 17078 0 13:14 ? 00:00:00 nginx: worker process
root 17086 2067 0 13:22 pts/0 00:00:00 grep --color=auto nginx
平滑升级完成!!!!
三,版本回退
我们在实际的生产环境中,有可能遇到升级失败的情况,那么这时我们之前备份的nginx执行脚本就起作用了,让我们还可以使用旧版本的nginx,使我们的服务不至于挂掉,我们称之为版本回退
1.将备份好的旧版本的脚本还原
2.唤醒旧版本的master进程
由于我们在之前已经关闭了旧版本的master进程,所以这里无法再唤醒了,但是我们可以通过步骤大家自己来实验
kill -HUP 14467(旧版本进程号) ##唤醒旧版本的master进程,使之产生新的worker进程
ps -ef | grep nginx ##查看nginx的进程,看是否产生了新的worker进程
3.同平滑升级一样,让回退版本接收新的用户请求。同时新版本的master进程的worker进程不再接收新的用户请求,只处理当前请求
kill -USR 17078(更新失败的nginx进程号)
4.关闭master进程的worker进程
kill -WINCH 17078
然后关闭新版本的master进程即可,版本回退!