一、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://www.ym68.cc/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

该文章采用「CC 协议」,转载必须注明作者和本文链接.
分类: Nginx