一、Nginx 平滑升级概述
随着网站并发访问量越来越高,Nginx版本换代越来越频繁,最新的Nginx更新了许多的新功能。生产环境中版本升级是必然的,但是线上业务不能停,此时Nginx的升级就是运维的重要工作了。
二、Nginx 平滑升级原理
多进程模式下的请求分配方式
Nginx 默认工作在多进程模式下,即主进程(master process)启动后完成配置加载和端口绑定等动作,fork 出指定数量的工作进程(worker process),这些子进程会持有监听端口的文件描述符(fd),并通过在该描述符上添加监听事件来接受连接(accept)。
信号的接收和处理
Nginx 主进程在启动完成后会进入等待状态,负责响应各类系统消息,如 SIGCHLD、SIGHUP、SIGUSR2 等。
Nginx 信号简介
主进程支持的信号
TERM, INT: 立刻退出
QUIT: 等待工作进程结束后再退出
KILL: 强制终止进程
HUP: 重新加载配置文件,使用新的配置启动工作进程,并逐步关闭旧进程。
USR1: 重新打开日志文件
USR2: 启动新的主进程,实现热升级
WINCH: 逐步关闭工作进程
工作进程支持的信号
TERM, INT: 立刻退出
QUIT: 等待请求处理结束后再退出
USR1: 重新打开日志文件
三、Nginx 升级前准备
旧版本安装配置
Nginx详细安装配置可参考:https://lolicp.com/linux/nginx/2020/53108.html
安装Nginx编译依赖
[root@admin ~]# yum -y install gd-devel wget make gcc-c++ gcc pcre-devel openssl openssl-devel
创建Nginx运行用户
[root@admin ~]# Nginx_User='nginx'
[root@admin ~]# useradd -M -s /sbin/nologin "${Nginx_User}"
创建Nginx安装目录
[root@admin ~]# Nginx_Path='/usr/local/nginx17'
[root@admin ~]# Nginx_Src_Path="${Nginx_Path}/src"
[root@admin ~]# mkdir -p "${Nginx_Src_Path}"
下载openssl-1.1.1g安装包
[root@admin ~]# cd /usr/src/
[root@admin src]# wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
[root@admin src]# tar zxf openssl-1.1.1g.tar.gz
下载ngx_cache_purge安装包[可选]
如不安装该扩展,需在configure中删除
[root@admin ~]# cd /usr/src/
[root@admin src]# wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz
[root@admin src]# tar zxf 2.3.tar.gz
安装Nginx 1.16.1
[root@admin ~]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@admin ~]# tar zxf nginx-1.16.1.tar.gz
[root@admin ~]# cd nginx-1.16.1
[root@admin nginx-1.16.1]# ./configure --prefix="${Nginx_Path}" --sbin-path="${Nginx_Path}/sbin/nginx" --modules-path="${Nginx_Path}/modules" --conf-path="${Nginx_Path}/conf/nginx.conf" --error-log-path="${Nginx_Path}/logs/error.log" --pid-path="${Nginx_Path}/tmp/nginx.pid" --lock-path="${Nginx_Path}/tmp/nginx.lock" --user="${Nginx_User}" --group="${Nginx_User}" --with-threads --with-file-aio --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-http_sub_module --add-module=/usr/src/ngx_cache_purge-2.3 --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt="-Wl,-E" --with-openssl=/usr/src/openssl-1.1.1g/
[root@admin nginx-1.16.1]# make -j 2 && make install
[root@admin nginx-1.16.1]# /usr/local/nginx17/sbin/nginx
三、Nginx 平滑升级准备
查看旧版Nginx配置
[root@admin ~]# /usr/local/nginx17/sbin/nginx -V
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.1.1g 21 Apr 2020
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx17 --sbin-path=/usr/local/nginx17/sbin/nginx --modules-path=/usr/local/nginx17/modules --conf-path=/usr/local/nginx17/conf/nginx.conf --error-log-path=/usr/local/nginx17/logs/error.log --pid-path=/usr/local/nginx17/tmp/nginx.pid --lock-path=/usr/local/nginx17/tmp/nginx.lock --user=nginx --group=nginx --with-threads --with-file-aio --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-http_sub_module --add-module=/usr/src/ngx_cache_purge-2.3 --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-openssl=/usr/src/openssl-1.1.1g/
编译新版本Nginx源码包,安装路径需与旧版一致
不需执行make install
[root@admin ~]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@admin ~]# tar zxf nginx-1.18.0.tar.gz -C /usr/src/
[root@admin ~]# cd /usr/src/nginx-1.18.0/
[root@admin nginx-1.18.0]# ./configure --prefix=/usr/local/nginx17 --sbin-path=/usr/local/nginx17/sbin/nginx --modules-path=/usr/local/nginx17/modules --conf-path=/usr/local/nginx17/conf/nginx.conf --error-log-path=/usr/local/nginx17/logs/error.log --pid-path=/usr/local/nginx17/tmp/nginx.pid --lock-path=/usr/local/nginx17/tmp/nginx.lock --user=nginx --group=nginx --with-threads --with-file-aio --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-http_sub_module --add-module=/usr/src/ngx_cache_purge-2.3 --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-openssl=/usr/src/openssl-1.1.1g/ &&make -j 2
备份Nginx旧版本并拷贝新版本二进制文件
[root@admin nginx-1.18.0]# mv /usr/local/nginx17/sbin/nginx{,.old}
[root@admin nginx-1.18.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE Makefile man objs README src
[root@admin nginx-1.18.0]# cp objs/nginx /usr/local/nginx17/sbin/
检查配置文件是否正确
[root@admin nginx-1.18.0]# /usr/local/nginx17/sbin/nginx -t
nginx: the configuration file /usr/local/nginx17/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx17/conf/nginx.conf test is successful
发送USR2信号
向主进程(master)发送 USR2 信号,Nginx 会启动一个新版本的 master 进程和对应工作进程,和旧版一起处理请求
[root@admin nginx-1.18.0]# ps aux |grep nginx |grep -v grep
root 60599 0.0 0.1 55408 1140 ? Ss 09:35 0:00 nginx: master process ./nginx
nginx 60600 0.0 0.1 55860 1904 ? S 09:35 0:00 nginx: worker process
[root@admin nginx-1.18.0]# kill -USR2 60599
[root@admin nginx-1.18.0]# ps aux |grep nginx |grep -v grep
root 60599 0.0 0.1 55408 1336 ? Ss 09:35 0:00 nginx: master process ./nginx
nginx 60600 0.0 0.1 55860 1904 ? S 09:35 0:00 nginx: worker process
root 60617 0.0 0.3 55420 3296 ? S 09:37 0:00 nginx: master process ./nginx
nginx 60618 0.0 0.1 55856 1896 ? S 09:37 0:00 nginx: worker process
发送WINCH信号
向旧的 Nginx 主进程(master)发送 WINCH 信号,它会逐步关闭自己的工作进程(主进程不退出),这时所有请求都会由新版 Nginx 处理
[root@admin nginx-1.18.0]# kill -WINCH 60599
[root@admin nginx-1.18.0]# ps aux |grep nginx |grep -v grep
root 60599 0.0 0.1 55408 1336 ? Ss 09:35 0:00 nginx: master process ./nginx
root 60617 0.0 0.3 55420 3296 ? S 09:37 0:00 nginx: master process ./nginx
nginx 60618 0.0 0.1 55856 1896 ? S 09:37 0:00 nginx: worker process
注意:回滚步骤,发送 HUP 信号
如果这时需要回退继续使用旧版本,可向旧的 Nginx 主进程发送 HUP 信号,它会重新启动工作进程, 仍使用旧版配置文件。然后可以将新版 Nginx 进程杀死(使用 QUIT、TERM、或者 KILL)
[root@admin nginx-1.18.0]# kill -HUP 60599
发送QUIT信号
升级完毕,可向旧的 Nginx 主进程(master)发送(QUIT、TERM、或者 KILL)信号,使旧的主进程退出
[root@admin nginx-1.18.0]# kill -QUIT 60599
[root@admin nginx-1.18.0]# ps aux |grep nginx |grep -v grep
root 60617 0.0 0.3 55420 3296 ? S 09:37 0:00 nginx: master process ./nginx
nginx 60618 0.0 0.1 55856 1896 ? S 09:37 0:00 nginx: worker process
验证Nginx版本号并访问测试
[root@admin nginx-1.18.0]# /usr/local/nginx17/sbin/nginx -v
nginx version: nginx/1.18.0