1、为什么要对 nginx 平滑升级
随着 nginx
越来越流行,并且 nginx
的优势也越来越明显,nginx
的版本迭代也来时加速模式,1.9.0版本的nginx更新了许多新功能,例如 stream
四层代理功能,伴随着 nginx
的广泛应用,版本升级必然越来越快,线上业务不能停,此时 nginx
的升级就是运维的工作了
nginx 方便地帮助我们实现了平滑升级。其原理简单概括,就是:
(1)在不停掉老进程的情况下,启动新进程。
(2)老进程负责处理仍然没有处理完的请求,但不再接受处理请求。
(3)新进程接受新请求。
(4)老进程处理完所有请求,关闭所有连接后,停止。
这样就很方便地实现了平滑升级。一般有两种情况下需要升级 nginx,一种是确实要升级 nginx 的版本,另一种是要为 nginx 添加新的模块
Nginx信号简介
主进程支持的信号
TERM
,INT
: 立刻退出QUIT
: 等待工作进程结束后再退出KILL
: 强制终止进程HUP
: 重新加载配置文件,使用新的配置启动工作进程,并逐步关闭旧进程。USR1
: 重新打开日志文件USR2
: 启动新的主进程,实现热升级WINCH
: 逐步关闭工作进程
工作进程支持的信号
TERM
,INT
: 立刻退出QUIT
: 等待请求处理结束后再退出USR1
: 重新打开日志文件
2、nginx后端健康检查
nginx自带健康检查的缺陷:
1.Nginx只有当有访问时后,才发起对后端节点探测。
2.如果本次请求中,节点正好出现故障,Nginx依然将请求转交给故障的节点,然后再转交给健康的节点处理,所以不会影响到这次请求的正常进行。但是会影响效率,因为多了一次转发。
3.自带模块无法做到预警
4.被动健康检查
标题使用第三方模块nginx_upstream_check_module:
1.区别于nginx自带的非主动式的心跳检测,淘宝开发的tengine自带了一个提供主动式后端服务器心跳检测模块。
2.若健康检查包类型为http,在开启健康检查功能后,nginx会根据设置的间隔向指定的后端服务器端口发送健康检查包,并根据期望的HTTP回复状态码来判断服务是否健康。
3.后端真实节点不可用,则请求不会转发到故障节点。
4.故障节点恢复后,请求正常转发。
下载包
第三方模块nginx_upstream_check_module
[root@webserver ~]# ls
master.zip ##解压缩
[root@webserver ~]# ls
master.zip nginx_upstream_check_module-master ##解压后的
有下面nginx rpm包 当前目录解压cd 进入
[root@webserver ~]# ls
nginx-1.19.5.tar.gz nginx-1.19.5
[root@webserver nginx-1.19.5]# patch -p1 < ../nginx_upstream_check_module-master/check_1.16.1+.patch
看一下模块,参考原来版本的配置参数,进行配置。
*特别要主要相关的安装路径、配置文件路径、日志路径等。
原有的参数不能少,假如想添加其它新模块,在最后添加相关配置参数即可。*
./configure --prefix=/usr/local/nginx --group=nginx --user=nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body --http-proxy-temp-path=/tmp/nginx/proxy --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_realip_module --with-stream --add-module=../nginx_upstream_check_module-master/
echo $? #看返回值
make #编译
/usr/local/nginx/sbin/nginx #绝对路径启动nginx,否则会报错
备份原 nginx 二进制文件
备份二进制文件和 nginx 的配置文件(期间nginx不会停止服务)
这里以原来的 Nginx 是编译安装的方式进行实验
[root@webserver nginx-1.19.5]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx20201221
复制新的nginx二进制文件,进入新的nginx源码包
[root@webserver nginx-1.19.5]# cp objs/nginx /usr/local/nginx/sbin/
测试新版本的nginx是否正常
[root@webserver nginx-1.19.5]# /usr/local/nginx/sbin/nginx -t
此时可以执行快速升级
在编译的目录中执行如下命令
[root@webserver nginx-1.19.5]# make upgrade #自动
/usr/local/nginx/sbin/nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
kill -USR2 `cat /run/nginx.pid`
sleep 1
test -f /run/nginx.pid.oldbin
kill -QUIT `cat /run/nginx.pid.oldbin`
手动
给nginx发送平滑迁移信号(若不清楚pid路径,请查看nginx配置文件)
[root@shark nginx-1.18.0]# kill -USR2 `cat /var/run/nginx.pid`
假如没有产生新的进程,检查错误日志是否出现了如下报错
最好将错误日志级别设置为 debug
execve() failed while executing new binary process "nginx" (2: No such file or directory
产生错误的原因是老的nginx进程启动的时候没有使用绝对路径。
解决办法,重新使用绝对路径启动 nginx
此时执行如下命令,可以看到新旧进程同时存在
[root@shark ~]# ps -ef |grep nginx
root 653 1 0 20:28 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 654 653 0 20:28 ? 00:00:00 nginx: worker process
nginx 655 653 0 20:28 ? 00:00:00 nginx: worker process
root 891 653 0 20:32 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 892 891 0 20:32 ? 00:00:00 nginx: worker process
nginx 893 891 0 20:32 ? 00:00:00 nginx: worker process
root 903 332 0 20:32 pts/0 00:00:00 grep --color=auto nginx
从容关闭旧的Nginx进程
[root@shark ~]# kill -WINCH `cat /var/run/nginx.pid.oldbin`
此时再次观察 nginx 进程,会发现旧的工作进程已经没有了,只要新旧的主进程和新的工作进程
[root@shark ~]# ps -ef |grep nginx
root 653 1 0 20:28 ? 00:00:00 nginx: master process /usr/sbin/nginx
root 891 653 0 20:32 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 892 891 0 20:32 ? 00:00:00 nginx: worker process
nginx 893 891 0 20:32 ? 00:00:00 nginx: worker process
root 919 332 0 20:33 pts/0 00:00:00 grep --color=auto nginx
结束工作进程,完成此次升级
[root@shark ~]# kill -QUIT `cat /var/run/nginx.pid.oldbin`
再次观察进程,只有新的主进程和工作进程了
[root@shark ~]# ps -ef |grep nginx
root 891 1 0 20:32 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 892 891 0 20:32 ? 00:00:00 nginx: worker process
nginx 893 891 0 20:32 ? 00:00:00 nginx: worker process
root 932 332 0 20:33 pts/0 00:00:00 grep --color=auto nginx
针对负载均衡配置
这一项 HTTP1.0 这么配置不会出问题 改为HTTP1.1 会出问题