原理:
nginx 支持热加载 热部署 ,在不打断用户请求的情况下更新版本
Nginx中的进程分为两类,一类是master进程(主进程),一类是worker进程(工作进程)
在平滑升级的时候首先替换master进程,同时替换的新的master进程和老版本的worker进程是兼容的,然后就是保持还在连接的worker进程处理完当前的请求并且不再接受请求,最后关闭之前的worker进程,实现平滑升级
如果更新失败立马回退,不可以多次更新
实验环境:
rhel7.3版本的虚拟机
两个不同版本的nginx源码安装包
一、配置过程:
1.下载两个不同版本的安装包
[root@server1 ~]# ls
nginx-1.15.8.tar.gz nginx-1.16.0.tar.gz
2.解压1.16.0版本,作为旧的版本
[root@server1 ~]# tar zxf nginx-1.16.0.tar.gz
[root@server1 ~]# ls
nginx-1.15.8.tar.gz nginx-1.16.0 nginx-1.16.0.tar.gz
[root@server1 ~]# cd nginx-1.16.0
[root@server1 nginx-1.16.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src
auto/ | 模块 操作系统的特性,帮助编译的 |
---|---|
changes | 每个版本之间的变化,版本的新特性,更新的细节 |
changes.ru | 俄罗斯版本的 |
conf | 配置文件 |
configure | 编译用的命令 |
contrib/vim | 提供nginx的语法检测 |
html | 默认发布目录 默认发布页 默认报错页 |
man | 手册 |
readme | 帮助 |
src | nginx源码目录 |
objs | 中间件的目录 |
不取消版本号,要观察版本的升级和回退
(1)关闭debug日志
[root@server1 nginx-1.16.0]# vim auto/cc/gcc
171 # debug
172 # CFLAGS="$CFLAGS -g"
(2)安装依赖性
[root@server1 nginx-1.16.0]# yum install -y pcre-devel zlib-devel gcc
[root@server1 nginx-1.16.0]# ./configure --prefix=/usr/local/nginx --with-file-aio
[root@server1 nginx-1.16.0]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@server1 nginx-1.16.0]# cd objs
[root@server1 objs]# ls
autoconf.err Makefile ngx_auto_config.h ngx_auto_headers.h ngx_modules.c src
make
[root@server1 nginx-1.16.0]# make
[root@server1 nginx-1.16.0]# ls
[root@server1 nginx-1.16.0]# cd objs/
[root@server1 objs]# ls
[root@server1 nginx-1.16.0]# make install
make install 实际上就是将二进制执行文件和一些配置文件复制到/usr/local/nginx目录下
4.配置nginx服务
(1)查看配置文件,第一行是nobody
不写的话nginx进程默认用户是nobody 可以开启服务用ps aux查看
[root@server1 nginx-1.16.0]# cd /usr/local
[root@server1 local]# cd nginx/
[root@server1 nginx]# ls
[root@server1 nginx]# cd conf
[root@server1 conf]# vim nginx.conf ##没有改变内容
[root@server1 conf]# ../sbin/nginx -t
[root@server1 conf]# ../sbin/nginx -V
[root@server1 conf]# ../sbin/nginx
(5)查看进程所有人是nobody
[root@server1 conf]# ps aux
[root@server1 conf]# useradd nginx
[root@server1 conf]#
[root@server1 conf]# id nginx
uid=1000(nginx) gid=1000(nginx) groups=1000(nginx)
[root@server1 conf]# ../sbin/nginx -s stop
[root@server1 conf]# vim nginx.conf ##改变用户
user nginx nginx;
worker_processes 2;
(9)先在系统安全的配置文件中设定nginx用户允许的最大文件数
[root@server1 conf]# vim /etc/security/limits.conf
63 nginx - nofile 65535
(10)再次编辑nginx配置文件,在配置文件设置最大并发数
[root@server1 conf]# vim nginx.conf ##改变最大并发数
12 events {
13 worker_connections 65535;
14 }
[root@server1 conf]# ../sbin/nginx
[root@server1 conf]#
[root@server1 conf]# ps aux
(12)打开浏览器测试,访问成功
访问到nginx的默认页面
二、更新nginx
1.解压另一个版本的nginx
[root@server1 ~]# cd nginx-1.15.8
[root@server1 nginx-1.15.8]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src
注意:千万不要make insatll 否则会把二进制执行文件复制到/usr/local下的nginx目录 覆盖之前的文件
(1)编译
[root@server1 nginx-1.15.8]# ./configure --prefix=/usr/local/nginx --with-file-aio
[root@server1 nginx-1.15.8]# ls
[root@server1 nginx-1.15.8]# cd objs/
[root@server1 objs]# ls
[root@server1 objs]# cd ..
[root@server1 nginx-1.15.8]# make
[root@server1 nginx-1.15.8]# cd objs/
[root@server1 objs]# ls
[root@server1 objs]# cd /usr/local/nginx/sbin/
[root@server1 sbin]# ls
nginx
当前还是老版本
[root@server1 sbin]# ./nginx -V
nginx version: nginx/1.16.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)
configure arguments: --prefix=/usr/local/nginx --with-file-aio
[root@server1 sbin]#
[root@server1 sbin]# cp nginx nginx.old
[root@server1 sbin]# ls
nginx nginx.old
(5)替换二进制文件(将新版本的二进制执行文件覆盖过去,要加 -f 否则报错正忙)
[root@server1 objs]# cp -f nginx /usr/local/nginx/sbin/nginx
cp: overwrite ‘/usr/local/nginx/sbin/nginx’? y
(6)查看nginx进程,一个master,两个worker
[root@server1 objs]# ps -ef | grep nginx
[root@server1 objs]# cd -
/usr/local/nginx/sbin
[root@server1 sbin]# ./nginx -V
注意:虽然当前版本已经变成了1.15.8也就是新的版本,但是他使用的进程还是之前旧版本的进程号,可以观察到进程的pid都是4810,所以说这个时候表面上看起来是更新成了新版本,但还是旧版本的在工作,接收客户端请求的仍然是1.16.0版本的nginx
三、平滑升级
1.kill -USR2 旧版本的主进程号 (让旧版本的worker进程不再接受请求)
[root@server1 objs]# kill -USR2 4810
[root@server1 objs]# ps -ef | grep nginx
可以看到现在有2个master,4个worker
2.kill -WINCH 旧版本的主进程号 (关闭旧版本的worker进程)
[root@server1 objs]# kill -WINCH 4810
[root@server1 objs]# ps -ef | grep nginx
可以看到现在有2个master,2个worker
旧版本的worker被关闭
3.查看版本号现在用的是新版本
[root@server1 objs]# /usr/local/nginx/sbin/nginx -V
kill -USER2 | 不再让worker进程接受请求,当前请求处理完就让worker进程退出 |
---|---|
kill -WINCH | 处理完关闭 |
kill -HUP | 启动进程 |
1.先将二进制执行文件还原,不加-f会提示文件正忙
[root@server1 objs]# cd /usr/local/nginx/sbin/
[root@server1 sbin]# ls
nginx nginx.old
[root@server1 sbin]# cp nginx.old nginx
cp: overwrite ‘nginx’? y
cp: cannot create regular file ‘nginx’: Text file busy
[root@server1 sbin]#
[root@server1 sbin]# cp -f nginx.old nginx
cp: overwrite ‘nginx’? y
[root@server1 sbin]# ps -ef | grep nginx
3.kill -HUP 旧版本的进程号 (拉起旧版本的worker进程)
[root@server1 sbin]# kill -HUP 4810
[root@server1 sbin]# ps -ef | grep nginx
2个master 4个worker
4.kill -USR2 新版本的主进程号 (让新版本的worker不再接受请求)
[root@server1 sbin]# kill -USR2 16940
[root@server1 sbin]# ps -ef | grep nginx
5.kill -WINCH 新版本的主进程号 (关闭新版本的worker进程)
[root@server1 sbin]# kill -WINCH 16940
[root@server1 sbin]# ps -ef | grep nginx
2个master,2个worker
6.查看版本号,是旧版本的nginx
[root@server1 sbin]# /usr/local/nginx/sbin/nginx -V