Nginx经常作为一个系统或者服务的访问入口,在升级nginx或者添加新模块时,我们希望尽可能地减少服务的不可用时间。Nginx的升级是可以做到不停服务的,也就是平滑升级。(本文涉及到的nginx是编译安装的方式,如果是yum等方式安装,此文章不适用。)
- 环境
原nginx版本: 1.14.2
目标升级版本:1.21.0
原nginx安装目录: /opt/nginx - 准备工作
检查当前nginx工作是否正常
在升级过程中,我们打开另一个终端,观察nginx进程的变化(每0.5s刷新一次)
- 编译新的nginx
[root@zabbix-agent-2 opt]# ls
nginx nginx-1.14.2 nginx-1.14.2.tar.gz nginx-1.21.0.tar.gz
[root@zabbix-agent-2 opt]# tar -xf nginx-1.21.0.tar.gz
[root@zabbix-agent-2 opt]# cd nginx-1.21.0
[root@zabbix-agent-2 nginx-1.21.0]# ../nginx/sbin/nginx -V
nginx version: nginx/1.14.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/opt/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
## **通过查看旧版本的安装参数,可以复制下面进行同步,也可以在此基础上加上新的参数**
[root@zabbix-agent-2 nginx-1.21.0]# ./configure --prefix=/opt/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
checking for OS
+ Linux 3.10.0-1127.19.1.el7.x86_64 x86_64
checking for C compiler ... found
+ using GNU C compiler
+ gcc version: 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
checking for gcc -pipe switch ... found
checking for -Wl,-E switch ... found
checking for gcc builtin atomic operations ... found
checking for C99 variadic macros ... found
checking for gcc variadic macros ... found
。。。
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
##下面只执行make命令,不要执行make install
[root@zabbix-agent-2 nginx-1.21.0]# make
make -f objs/Makefile
make[1]: Entering directory `/opt/nginx-1.21.0'
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
。。。。
objs/src/http/modules/ngx_http_upstream_keepalive_module.o \
objs/src/http/modules/ngx_http_upstream_zone_module.o \
objs/src/http/modules/ngx_http_stub_status_module.o \
objs/ngx_modules.o \
-ldl -lpthread -lcrypt -lpcre -lssl -lcrypto -ldl -lpthread -lz \
-Wl,-E
sed -e "s|%%PREFIX%%|/opt/nginx|" \
-e "s|%%PID_PATH%%|/opt/nginx/logs/nginx.pid|" \
-e "s|%%CONF_PATH%%|/opt/nginx/conf/nginx.conf|" \
-e "s|%%ERROR_LOG_PATH%%|/opt/nginx/logs/error.log|" \
< man/nginx.8 > objs/nginx.8
make[1]: Leaving directory `/opt/nginx-1.21.0'
- 新命令替换旧命令
[root@zabbix-agent-2 nginx-1.21.0]# mv /opt/nginx/sbin/nginx /opt/nginx/sbin/nginx-1.14
[root@zabbix-agent-2 nginx-1.21.0]# cp objs/nginx /opt/nginx/sbin/
- 给进程发送信号
[root@zabbix-agent-2 nginx-1.21.0]# kill -USR2 `cat /opt/nginx/logs/nginx.pid`
# 主进程将重命名它的 .pid 文件为 .oldbin,然后执行新的可执行程序,依次启动新的主进程和新的工作进程.
同时观察进行的变化,发现启动了另外一组进程,准备接管新的请求。
给旧的主进发WINCH信号,把旧的主进程关闭,把所有请求转到新的主进程,但是原有的请求不会中断,有新请求的时候发到新进程
[root@zabbix-agent-2 nginx-1.21.0]# kill -WINCH `cat /opt/nginx/logs/nginx.pid.oldbin`
同时观察进程的变化,旧的进程已经关闭,但是旧的master进程还在。
升级成功,发送 QUIT 信号给旧的主进程使其退出而只留下新的进程运行.
[root@zabbix-agent-2 nginx-1.21.0]# kill -QUIT `cat /opt/nginx/logs/nginx.pid.oldbin`
观察进程的变化,旧的master进程也成功退出。
- 确认新版
[root@zabbix-agent-2 nginx]# ./sbin/nginx -V
nginx version: nginx/1.21.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/opt/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module
可以看到nginx已经升级到新版本,升级完成。