目录
1. 为什么需要nginx平滑升级
2.Nginx平滑升级原则
3. 前置准备
4.安装模拟升级到较旧的Nginx版本
5. 模拟真实业务场景
6.下载并获取扩展模块
7. 模拟Nginx升级
一. 为什么要对 nginx 平滑升级
随着nginx越来越流行,nginx的好处越来越明显,nginx的版本迭代也进入了加速模式。 nginx 1.9.0版本更新了许多新功能,包括streams 4。层代理功能随着nginx的普及,版本升级必然会变得更快,线上业务无法停止。
nginx 对于平滑升级很有用。这个原理的简单总结如下。 (1) 开始一个新的进程而不停止旧的进程。 (2)旧进程负责处理尚未处理的请求,但将不再接受处理请求。 (3)新进程接受新请求。 (4)处理完所有请求并关闭所有连接后,停止旧进程。 这有利于平滑升级。一般来说,需要升级nginx有两种情况。一是实际升级nginx的版本,二是给nginx添加新的模块。
二. Nginx 平滑升级原理
多进程模式下如何分配请求
Nginx 默认以多进程模式运行。即master进程启动后,完成加载配置、端口绑定等动作,并fork出指定数量的worker进程,这些子进程保存文件。指定监听端口(fd),并在描述符中添加监听事件以接受连接(accept)。
信号接收与处理
nginx主进程一旦启动,就处于等待状态,负责响应SIGCHLD、SIGHUP、SIGUSR2等各种系统消息。
Nginx 信号概述
主进程支持的信号
TERM,INT: 立即终止
QUIT: 等待工作进程完成后再退出
KILL: 终止进程
HUP: 重新加载配置文件,使用新配置启动工作进程,并逐渐关闭旧进程。
USR1: 重新打开日志文件
USR2:启动新的主进程,实现热升级。
WINCH: 逐渐关闭工作进程
工作进程支持的信号
TERM,INT: 立即终止
QUIT: 请等待请求处理完后再退出
USR1: 重新打开日志文件
三. 前提准备
准备初始化的虚拟机
本地主机Rocky_linux9.4192.168.226.20
关闭防火墙和SElinux
在继续基本虚拟机配置脚本之前,首先运行该脚本。
#!/bin/bash
#**************************************************** * ******
# * 文件名: Rocky_linux
# * 作者: 驼鹿
# * 电子邮件: zzdict@gmail.com/elk_deer@foxmail.com
# * 创建时间: 2024-06-15 20:12
# * 描述:
#**************************************************** * ******
# 检查脚本是否以root 用户身份运行
if [ \’$(id -u)\’ -ne 0 ];
大胆
输入设置1
tput setaf 3
echo \’请以root 用户身份运行此脚本。 \’
输入sgr0
1号出口
菲
# 启用网络接口
启用网络接口(){
本地接口=$1
如果ip链接设置“$interface”。
大胆
tput setaf 2
echo \’网络接口$interface已启用。 \’
输入sgr0
除此之外
大胆
输入设置1
echo \’无法启用网络接口$interface。请检查接口名称。 \’
输入sgr0
1号出口
菲
}
# 设置YUM 源
配置yum_repos() {
sed -e \’s|^mirrorlist=|#mirrorlist=|g\’ \\
-e \’s|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g\’ \\
-i.bak \\
/etc/yum.repos.d/Rocky-*.repo
大胆
tput setaf 2
echo \’YUM 源配置已更新。 \’
输入sgr0
dnf 制作缓存
yum -y 安装epel-release
}
# 停止并禁用防火墙并禁用SELinux
配置安全(){
systemctl 停止防火墙。 systemctl 禁用防火墙。
防火墙-cmd –重新加载
大胆
tput setaf 2
echo \’防火墙已停止并禁用。 \’
输入sgr0
sed -i \’s/SELINUX=enforcing/SELINUX=disabled/\’ /etc/selinux/config
大胆
tput setaf 2
echo \’SELinux 已禁用。 \’
输入sgr0
}
# 检查并安装chrony时间同步
函数install_and_sync_time_with_chrony() {
# 检查是否安装了chrony
if 命令-v chronyd /dev/null;
sudo dnf install -y chrony /dev/null
# 检查是否安装成功
if 命令-v chronyd /dev/null;
大胆
输入设置1
echo \’慢性安装失败。请检查您的包管理器并重试。 \’
输入sgr0
1号出口
除此之外
大胆
tput setaf 2
echo \’chrony 安装成功。 \’
输入sgr0
菲
除此之外
大胆
tput setaf 2
echo \’Crony 已安装。 \’
输入sgr0
菲
# 确保安装了其他必需的包
sudo dnf install -y vim wget 解压tar lrzsz /dev/null
如果[ $? -eq 0 ];
大胆
tput setaf 2
echo \’其他软件包安装成功。 \’
输入sgr0
除此之外
大胆
输入设置1
echo \’安装其他包失败。 \’
输入sgr0
1号出口
菲
}
# 启动chronyd 服务并启用启动功能
当sudo systemctl 启动chronyd 时当sudo systemctl 启用chronyd 时。
大胆
tput setaf 2
echo \’chronyd 服务已成功启动并设置为在启动时启动。 \’
输入sgr0
除此之外
大胆
输入设置1
echo \’chronyd 服务启动或启用失败。检查systemctl的状态。 \’
输入sgr0
1号出口
菲
# 强制同步时间
sudo chronyc – 执行步骤
大胆
tput setaf 2
echo \’时间同步成功完成。 \’
输入sgr0
}
# 自定义IP地址
配置IP 地址(){
大胆
眨
输入设置1
read -p \’****请输入你要设置的IP : \’ ip_a
输入sgr0
大胆
眨
tput setaf 6
read -p \’****请输入您要配置的网关:\’ gat
输入sgr0
大胆
眨
tput setaf 3
read -p \’*****请输入您要配置的DNS :\’ dnns
输入sgr0
# 查看当前连接的名称
connection_name=$(nmcli -t -f NAME,DEVICE con show –active | grep -E \’ens33|有线连接1\’ | Cut -d: -f1)
if [[ \’$connection_name\’==\’ens33\’ ]];
# ens33 连接设置
nmcli con mod \’ens33\’ ipv4.method 手动ipv4.addresses \’${ip_a}/24\’ ipv4.gateway \’${gat}\’ ipv4.dns \’${dnns}\’ 自动连接是
elif [[ \’$connection_name\’==\’有线连接1\’ ]];
# 设置有线连接1连接
nmcli con mod \’有线连接1\’ ipv4.method 手动ipv4.addresses \’${ip_a}/24\’ ipv4.gateway \’${gat}\’ ipv4.dns \’${dnns}\’ 自动连接是
除此之外
大胆
输入设置1
echo \’无法识别的网络连接名称:$connection_name\’
输入sgr0
返回1
菲
tput设置5
tput 设置15
大胆
echo \’IP地址已配置成功,系统即将重启。 \’
输入sgr0
nmcli 启动\’$connection_name\’
重启
}
主功能
主要的() {
本地接口=\’ens33\’
启用_网络_接口\’$接口\’
配置yum_repos
配置安全
install_and_sync_time_with_chrony
配置IP 地址\’$ 接口\’
}
# 调用主函数
主要的
访问官网下载两个不同版本
官网:nginx:下载
下载两个不同的版本进行实验,并从较低版本升级到较高版本。
将下载的两个安装包上传到虚拟机中,如下图。
[root@localhost ~]# ll
总计2268
-rw——.1根根815 6月6日14:00 anaconda-ks.cfg
-rw-r–r– 1 root root 1062124 六月22 00:38 nginx-1.20.2.tar.gz
-rw-r–r– 1 root root 1244738 六月21 21:19 nginx-1.26.1.tar.gz
-rw-r–r– 1 root root 4251 六月17 23:50 Rocky_linux.sh
四. 安装一个模拟被升级旧Nginx版本
1.安装依赖工具
[root@localhost ~]# yum install -y gcc gcc-c++ pcre-devel openssl-devel zlib-devel
2.解压1.20.2版本安装包。
[root@localhost ~]# ls
anaconda-ks.cfg nginx-1.20.2.tar.gz nginx-1.26.1.tar.gz rocky_linux.sh
[root@localhost ~]# tar -zxf nginx-1.20.2.tar.gz
3.切换到解压后的目录
[root@localhost ~]# ls
anaconda-ks.cfg nginx-1.20.2 nginx-1.20.2.tar.gz nginx-1.26.1.tar.gz rocky_linux.sh
[root@localhost ~]# cd nginx-1.20.2
[root@localhost nginx-1.20.2]# ls
更改CHANGES.ru 许可证自述文件auto conf 配置contrib html man src
4. 预编译
这里有两个模块没有写入代码。用于用少量模块模拟此类场景,方便后续升级和扩展。
[root@localhost nginx-1.20.2]# ./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_模块
5.编译安装
[root@localhost nginx-1.20.2]# make make install
6.创建nginx系统用户
[root@localhost nginx-1.20.2]# useradd –system –no-create-home –shell /sbin/nologin nginx
7、创建目录,临时存放客户端请求数据和缓存文件。
[root@localhost nginx-1.20.2]# mkdir -p /tmp/nginx/client_body
8.启动nginx
[root@localhost nginx-1.20.2]# /usr/local/nginx/sbin/nginx
9.验证nginx是否正常工作
[root@localhost nginx-1.20.2]#curl -Ik 192.168.226.20
HTTP/1.1 200 好
服务器: nginx/1.20.2
日期: 2024 年6 月22 日星期六05:16:03 GMT
内容类型: 文本/html
内容长度: 612
最后修改时间: 2024 年6 月22 日星期六01:00:47 GMT
连接:保持活动
ETag:\’6676223f-264\’
接受范围: 字节
或者,打开浏览器并更改主机的IP 地址。
五. 模拟真实业务场景
使用go代码不断向某个主机地址发送请求,模拟用户访问,模拟真实的业务场景。
监视升级过程中是否发生故障,或者是否存在任何中断性访问。当然,少量的失败是可以接受的。
包主
进口(
“FMMT”
“艾欧”
“网络/http”
\’时间\’
)
//ANSI颜色代码
持续的(
红色=\’\\033[31m\’
绿色=\’\\033[32m\’
黄色=\’\\033[33m\’
重置颜色=\’\\033[0m\’
)
//记录成功、失败、无响应和服务暂时不可用(503)请求的数量。
var successCount int 变量
varfailureCount int 变量
var 无响应计数int
var tempUnavailableCount int //503 添加一个新变量来跟踪服务不可用状态的请求数量
//makeRequest 向指定的URL 发送GET 请求,并根据响应是否成功以不同颜色打印响应状态和经过的时间。
func makeRequest(url 字符串, 尝试int) {
开始时间:=时间.Now()
响应,错误:=http.Get(url)
经过的时间:=time.since(startTime)
如果出现错误!=nil {
//如果由于网络或服务器问题导致请求失败,则视为“未响应”。
fmt.Printf(\'[%d] %s请求未响应: %s %.4f 秒%s\\n\’, 已尝试, RedColor, 错误, elapsedTime.Seconds(), ResetColor)
无回复计数++
返回
}
defer func(Body io.ReadCloser) {
错误:=Body.Close()
如果出现错误!=nil {
fmt.Printf(\’关闭响应正文时出错: %s\\n\’, err)
}
}(每个身体)
颜色:=绿色
如果resp.StatusCode==503 {
颜色=黄色
tempUnavailableCount++ //返回503 状态代码的请求计数。
否则如果resp.StatusCode !=200 {
颜色=红色
失败次数++
} 除此之外{
成功次数++
}
//根据状态码,以对应颜色输出响应状态码和持续时间
fmt.Printf(\'[%d] %s%d %.4f 秒%s\\n\’, Trial, color, resp.StatusCode, elapsedTime.Seconds(), ResetColor)
}
函数主() {
url :=\’http://192.168.226.20\’ //选择要测试的地址
totalAttempts :=20000 //自定义请求次数
开始时间:=时间.Now()
尝试:=1; 尝试=总尝试++ {
makeRequest(URL, 尝试)
time.Sleep(1 * time.Second) //每个请求之间等待1 秒
}
总运行时间:=time.since(startTime)
成功率:=(float64(成功计数)/float64(总尝试次数)) * 100
失败率:=(float64(failureCount)/float64(totalAttempts)) * 100
un 响应速度:=(float64(un 响应次数)/float64(总尝试次数)) * 100
tempUnavailableRate :=(float64(tempUnavailableCount)/float64(totalAttempts)) * 100 //计算503个状态码的比率
fmt.Printf(\’%s总运行时间: %.4f 秒%s\\n\’, ResetColor,totalElapsedTime.Seconds(), ResetColor)
fmt.Printf(\’成功率: %.2f%%,失败率: %.2f%%,无响应请求率: %.2f%%,服务暂时不可用请求率(503) : %.2f%% \\n\’ 、成功率、失败率、未知率、tempUnavailableRate)
}
如图所示:
六. 下载获取一个扩展模块
1.下载扩展模块
[root@localhost ~]# cd
[root@localhost ~]# wget https://github.com/zls0424/ngx_req_status/archive/master.zip -O ngx_req_status
.zip
2. 解压并查看
[root@localhost ~]# unzip ngx_req_status.zip
Archive: ngx_req_status.zip
428ffbb511fcb456218b4d2e6fb2f6f3e5abcf08
creating: ngx_req_status-master/
inflating: ngx_req_status-master/README
inflating: ngx_req_status-master/README.md
inflating: ngx_req_status-master/config
inflating: ngx_req_status-master/module_patch.sh
inflating: ngx_req_status-master/ngx_http_req_status_module.c
inflating: ngx_req_status-master/write_filter-1.7.11.patch
inflating: ngx_req_status-master/write_filter.patch
[root@localhost ~]# ll
total 2280
-rw——-. 1 root root 815 Jun 6 14:00 anaconda-ks.cfg
drwxr-xr-x 9 1001 1001 186 Jun 22 00:58 nginx-1.20.2
-rw-r–r– 1 root root 1062124 Jun 22 00:38 nginx-1.20.2.tar.gz
drwxr-xr-x 8 502 games 158 May 29 22:30 nginx-1.26.1
-rw-r–r– 1 root root 1244738 Jun 21 21:19 nginx-1.26.1.tar.gz
drwxr-xr-x 2 root root 169 Oct 21 2015 ngx_req_status-master
-rw-r–r– 1 root root 11237 Jun 22 13:50 ngx_req_status.zip
-rw-r–r– 1 root root 4251 Jun 17 23:50 rocky_linux.sh
3.解压升级的nginx版本压缩包
[root@localhost ~]# cd
[root@localhost ~]# tar -zxf nginx-1.26.1.tar.gz
4.将该模块拷贝到升级的nginx版本解压后的目录里
[root@localhost ~]# cp -r ngx_req_status-master/ nginx-1.26.1/
5.安装一些依赖包,并确保都已安装
[root@localhost ~]# yum -y install pcre pcre-devel openssl openssl-devel gcc gcc-c++ zlib zlib-devel
[root@localhost ~]# yum -y install patch.x86_64
七. 模拟升级Nginx
1.进入升级的nginx版本目录里,可以看到刚拷贝进来的扩展模块也在
[root@localhost ~]# cd nginx-1.26.1/
[root@localhost nginx-1.26.1]# ll
total 828
-rw-r–r– 1 502 games 327587 May 29 22:30 CHANGES
-rw-r–r– 1 502 games 501144 May 29 22:30 CHANGES.ru
-rw-r–r– 1 502 games 1397 May 28 21:28 LICENSE
-rw-r–r– 1 502 games 49 May 28 21:28 README
drwxr-xr-x 6 502 games 4096 Jun 22 13:29 auto
drwxr-xr-x 2 502 games 168 Jun 22 13:29 conf
-rwxr-xr-x 1 502 games 2611 May 28 21:28 configure
drwxr-xr-x 4 502 games 72 Jun 22 13:29 contrib
drwxr-xr-x 2 502 games 40 Jun 22 13:29 html
drwxr-xr-x 2 502 games 21 Jun 22 13:29 man
drwxr-xr-x 2 root root 169 Jun 22 13:58 ngx_req_status-master
drwxr-xr-x 9 502 games 91 May 29 22:30 src
2.应用相应的补丁
[root@localhost nginx-1.26.1]# patch -p1 < ./ngx_req_status-master/write_filter-1.7.11.patch
3.预编译
和上面那个预编译的步骤相比,多加了两个模块
[root@localhost nginx-1.26.1]# ./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 –with-http_image_filter_module –add-module=./ngx_req_status-master
4.编译
[root@localhost nginx-1.26.1]# make
升级不要再执行make install
5.备份旧版本nginx
[root@localhost nginx]# cd /usr/local/nginx/sbin
[root@localhost sbin]# mv nginx nginx.bak
[root@localhost sbin]# ll
total 4268
-rwxr-xr-x 1 root root 4368512 Jun 22 09:00 nginx.bak
6.拷贝新版本的nginx到当前目录
[root@localhost sbin]# cp /root/nginx-1.26.1/objs/nginx ./
[root@localhost sbin]# ll
total 9336
-rwxr-xr-x 1 root root 5186960 Jun 22 14:20 nginx
-rwxr-xr-x 1 root root 4368512 Jun 22 09:00 nginx.bak
7.测试新版本的nginx是否正常
[root@localhost sbin]# ./nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
8.给nginx发送平滑迁移信号(若不清楚pid路径,请查看nginx配置文件)
[root@localhost sbin]# kill -USR2 `cat /var/run/nginx.pid`
9.查看nginx pid,会出现一个nginx.pid.oldbin
[root@localhost sbin]# ll /var/run/nginx.pid*
-rw-r–r– 1 root root 5 Jun 22 14:25 /var/run/nginx.pid
-rw-r–r– 1 root root 5 Jun 22 13:14 /var/run/nginx.pid.oldbin
10.查看当前nginx进程
会有两组nginx进程,一组是前面旧版本的13:14分运行的,一组是刚刚14:24运行的,即新起来的进程
[root@localhost sbin]# ps aux |grep nginx
root 1435 0.0 0.1 9556 2528 ? Ss 13:14 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 1436 0.0 0.2 13948 5088 ? S 13:14 0:03 nginx: worker process
root 6202 0.0 0.3 9684 6528 ? S 14:24 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 6203 0.0 0.2 13980 5100 ? S 14:24 0:00 nginx: worker process
root 6207 0.0 0.1 3876 1920 pts/0 S+ 14:26 0:00 grep –color=auto nginx
11.从容关闭旧的Nginx进程
此时旧版本的worker进程会关闭
[root@localhost sbin]# kill -WINCH `cat /var/run/nginx.pid.oldbin`
注意声明:
不重载配置启动旧的工作进程,该步骤是在如果新进程察觉到有问题,回滚启用旧nginx进程。如果没有问题,此步骤不操作。
kill -HUP `cat /var/run/nginx.pid.oldbin`
12.结束工作进程,完成此次升级
[root@localhost sbin]# kill -QUIT `cat /var/run/nginx.pid.oldbin`
13.验证Nginx是否升级成功
[root@localhost sbin]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.26.1
built by gcc 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: –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=./ngx_req_status-master
[root@localhost sbin]# curl -Ik 192.168.226.20
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sat, 22 Jun 2024 06:38:12 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sat, 22 Jun 2024 01:00:47 GMT
Connection: keep-alive
ETag: \”6676223f-264\”
Accept-Ranges: bytes
旧版本的nginx需要观察一段时间,确定不会影响业务需求再进行删除。
#以上关于Nginx平滑升级的相关内容来源网络仅供参考,相关信息请以官方公告为准!
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91623.html