当前位置: 首页 > news >正文

Nginx 零停机平滑升级完整指南

核心目标:升级过程中用户访问完全无感知,实现真正的零停机更新

1. 平滑升级原理与价值

什么是真正的平滑升级?

平滑升级(Hot Upgrade)是指在不停止服务的情况下,通过信号控制实现新旧Nginx进程无缝切换,用户访问完全不受影响。

传统方式 vs 平滑升级对比

方式操作流程业务影响
传统重启方式停止服务 → 替换二进制 → 重启服务服务中断,用户看到502错误
伪平滑升级停止服务 → 替换 → 启动 → 信号切换短暂中断,用户体验差
真正平滑升级信号控制 → 新旧进程并行 → 优雅切换零停机,用户完全无感知

应用场景

  • 安全漏洞紧急修复
  • 性能优化版本更新
  • 功能增强版本升级
  • 生产环境维护窗口期短
  • 高可用业务场景

2. 环境准备与预检查

环境说明

# 当前运行环境
[root@web01 ~]# nginx -v
nginx version: nginx/1.22.0# 新版本准备
[root@web01 ~]# ls -lh /tmp/nginx-1.24.0
-rwxr-xr-x 1 root root 1.3M Nov 12 14:30 /tmp/nginx-1.24.0

预升级检查(不停止服务)

#!/bin/bash
# 预检查脚本 - 确保升级条件满足echo "=== Nginx 平滑升级预检查 ==="# 1. 检查当前Nginx运行状态
echo "1. 检查Nginx运行状态..."
if ! systemctl is-active nginx > /dev/null; thenecho "Nginx 服务未运行"exit 1
fi
echo " Nginx 服务运行正常"# 2. 查看进程信息
echo "2. 检查Nginx进程..."
ps -ef | grep nginx | grep -v grep# 3. 确认PID文件位置
echo "3. 检查PID文件..."
if [ ! -f /var/run/nginx.pid ]; thenecho "PID文件不存在: /var/run/nginx.pid"exit 1
fi
echo " PID文件: /var/run/nginx.pid ($(cat /var/run/nginx.pid))"# 4. 检查端口监听
echo "4. 检查端口监听..."
ss -lntup | grep :80 || echo "80端口未监听"# 5. 测试新版本兼容性
echo "5. 测试新版本兼容性..."
if [ ! -f "/tmp/nginx-1.24.0" ]; thenecho "新版本二进制文件不存在"exit 1
fiif ! /tmp/nginx-1.24.0 -t > /dev/null 2>&1; thenecho "新版本配置测试失败"exit 1
fi
echo " 新版本配置测试通过"# 6. 版本信息对比
echo "6. 版本信息:"
echo "   当前版本: $(nginx -v 2>&1)"
echo "   目标版本: $(/tmp/nginx-1.24.0 -v 2>&1)"echo "=== 预检查完成,可以开始升级 ==="

3. 手动平滑升级详细步骤

真正的零停机升级流程

老Nginx主进程(1234)↓ (发送USR2信号 - 启动新进程)
新Nginx主进程(5678)启动,老进程继续运行↓ (新旧进程并行处理请求)
老Worker进程优雅关闭,新Worker接管所有请求↓ (可选发送QUIT信号)
完全关闭老Master进程

具体操作步骤

步骤1:备份原有二进制(服务继续运行)
# 备份当前Nginx二进制文件,不停止服务
[root@web01 ~]# cp /usr/sbin/nginx /usr/sbin/nginx.backup.$(date +%Y%m%d_%H%M%S)# 验证备份
[root@web01 ~]# ls -lh /usr/sbin/nginx*
-rwxr-xr-x 1 root root 1.2M Nov 12 10:00 /usr/sbin/nginx
-rwxr-xr-x 1 root root 1.2M Nov 12 14:35 /usr/sbin/nginx.backup.20241112_1435
步骤2:替换二进制文件(不重启服务)
# 直接替换二进制文件,原进程继续运行旧版本
[root@web01 ~]# cp /tmp/nginx-1.24.0 /usr/sbin/nginx
[root@web01 ~]# chmod +x /usr/sbin/nginx# 验证替换成功(文件已更新,但进程还是旧的)
[root@web01 ~]# /usr/sbin/nginx -v
nginx version: nginx/1.24.0[root@web01 ~]# ps -ef | grep nginx
root      1234     1  0 10:00 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx     1235  1234  0 10:00 ?        00:00:00 nginx: worker process
步骤3:发送USR2信号启动新进程
# 发送USR2信号给主进程,启动新的Nginx实例(零停机)
[root@web01 ~]# kill -USR2 $(cat /var/run/nginx.pid)# 检查新老PID文件生成
[root@web01 ~]# ls -la /var/run/nginx.pid*
-rw-r--r-- 1 root root 5 Nov 12 14:36 /var/run/nginx.pid      # 新进程PID
-rw-r--r-- 1 root root 5 Nov 12 10:00 /var/run/nginx.pid.oldbin  # 老进程PID[root@web01 ~]# cat /var/run/nginx.pid.oldbin
1234
步骤4:验证新老进程共存
# 查看进程树,确认新老进程都在运行
[root@web01 ~]# ps -ef | grep nginx
root      1234     1  0 10:00 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx     1235  1234  0 10:00 ?        00:00:00 nginx: worker process
root      5678  1234  0 14:36 ?        00:00:00 nginx: master process /usr/sbin/nginx  
nginx     5679  5678  0 14:36 ?        00:00:00 nginx: worker process# 检查端口监听(新旧进程都监听80端口)
[root@web01 ~]# ss -lntup | grep :80
tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=5679,fd=10),("nginx",pid=5678,fd=10),("nginx",pid=1235,fd=10),("nginx",pid=1234,fd=10))# 测试服务可用性(零中断)
[root@web01 ~]# curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0  # 已经由新版本响应
步骤5:优雅关闭老Worker进程
# 发送WINCH信号,优雅关闭老Master进程的Worker进程
[root@web01 ~]# kill -WINCH $(cat /var/run/nginx.pid.oldbin)# 再次检查进程状态(老Worker进程已关闭)
[root@web01 ~]# ps -ef | grep nginx
root      1234     1  0 10:00 ?        00:00:00 nginx: master process /usr/sbin/nginx
root      5678  1234  0 14:36 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx     5679  5678  0 14:36 ?        00:00:00 nginx: worker process# 验证服务完全由新进程处理
[root@web01 ~]# for i in {1..5}; do curl -s http://localhost/nginx_status | grep Active; done
Active connections: 1 
Active connections: 1
Active connections: 1
Active connections: 1
Active connections: 1
步骤6:(可选)完全关闭老Master进程
# 发送QUIT信号,完全关闭老Master进程
[root@web01 ~]# kill -QUIT $(cat /var/run/nginx.pid.oldbin)# 最终进程状态
[root@web01 ~]# ps -ef | grep nginx
root      5678     1  0 14:36 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx     5679  5678  0 14:36 ?        00:00:00 nginx: worker process# 清理旧PID文件
[root@web01 ~]# rm -f /var/run/nginx.pid.oldbin
步骤7:验证升级结果
# 确认新版本正常运行
[root@web01 ~]# nginx -v
nginx version: nginx/1.24.0# 全面测试服务功能
[root@web01 ~]# curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Wed, 12 Nov 2025 06:36:00 GMT
Content-Type: text/html[root@web01 ~]# systemctl status nginx
● nginx.service - nginx - high performance web serverLoaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)Active: active (running) since Wed 2025-11-12 10:00:00 CST; 4h agoMain PID: 5678 (nginx)

4. 企业级自动化平滑升级脚本

零停机自动化升级脚本

创建专业升级脚本:/usr/local/bin/nginx_zero_downtime_upgrade.sh

#!/bin/bash
#
# Nginx 零停机平滑升级脚本
# 支持回滚、详细日志、实时监控
# 版本: 3.0set -e# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'# 日志函数
log() {echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a /var/log/nginx_upgrade.log
}warn() {echo -e "${YELLOW}[WARN] $1${NC}" | tee -a /var/log/nginx_upgrade.log
}error() {echo -e "${RED}[ERROR] $1${NC}" | tee -a /var/log/nginx_upgrade.logexit 1
}info() {echo -e "${BLUE}[INFO] $1${NC}" | tee -a /var/log/nginx_upgrade.log
}# 配置变量
NGINX_PID_FILE="/var/run/nginx.pid"
NGINX_BIN="/usr/sbin/nginx"
BACKUP_DIR="/opt/nginx_backup_$(date +%Y%m%d_%H%M%S)"
LOG_FILE="/var/log/nginx_upgrade.log"
NEW_NGINX_BINARY="$1"# 使用说明
usage() {echo "用法: $0 <新nginx二进制文件路径>"echo "示例: $0 /tmp/nginx-1.24.0"echo ""echo "特性:"echo "  - 真正的零停机升级"echo "  - 自动回滚机制"echo "  - 详细日志记录"echo "  - 实时健康检查"exit 1
}# 参数检查
check_params() {if [ -z "$NEW_NGINX_BINARY" ]; thenerror "请指定新Nginx二进制文件路径"usagefiif [ ! -f "$NEW_NGINX_BINARY" ]; thenerror "新Nginx二进制文件不存在: $NEW_NGINX_BINARY"fiif [ ! -x "$NEW_NGINX_BINARY" ]; thenlog "添加执行权限到新二进制文件..."chmod +x "$NEW_NGINX_BINARY" || error "无法添加执行权限"fi
}# 环境检查
check_environment() {log "=== 开始环境检查 ==="# 检查Nginx是否运行if [ ! -f "$NGINX_PID_FILE" ]; thenerror "Nginx未运行或PID文件不存在: $NGINX_PID_FILE"filocal OLD_PID=$(cat "$NGINX_PID_FILE")if ! ps -p "$OLD_PID" > /dev/null 2>&1; thenerror "Nginx主进程不存在 (PID: $OLD_PID)"fi# 检查新版本兼容性log "测试新版本配置兼容性..."if ! "$NEW_NGINX_BINARY" -t > /dev/null 2>&1; thenerror "新版本配置测试失败,请检查nginx.conf语法"fi# 版本信息local CURRENT_VERSION=$("$NGINX_BIN" -v 2>&1 | head -n1)local NEW_VERSION=$("$NEW_NGINX_BINARY" -v 2>&1 | head -n1)log "当前版本: $CURRENT_VERSION"log "目标版本: $NEW_VERSION"# 检查系统资源local MEM_FREE=$(free -m | awk 'NR==2{print $4}')if [ "$MEM_FREE" -lt 100 ]; thenwarn "系统可用内存较低: ${MEM_FREE}MB"fi
}# 备份当前版本
backup_current() {log "=== 备份当前版本 ==="mkdir -p "$BACKUP_DIR" || error "创建备份目录失败"# 备份二进制文件cp "$NGINX_BIN" "$BACKUP_DIR/nginx.old" || error "备份当前Nginx失败"cp "$NEW_NGINX_BINARY" "$BACKUP_DIR/nginx.new" || error "备份新Nginx失败"# 备份配置文件if [ -d "/etc/nginx" ]; thencp -r /etc/nginx/ "$BACKUP_DIR/nginx_conf_backup/" && \log "配置文件备份完成"elsewarn "/etc/nginx 目录不存在,跳过配置文件备份"fi# 备份当前进程信息ps aux | grep nginx > "$BACKUP_DIR/nginx_processes.bak"ss -lntup | grep nginx > "$BACKUP_DIR/nginx_ports.bak"log "备份完成: $BACKUP_DIR"
}# 实时监控函数
monitor_services() {local duration=${1:-5}log "监控服务状态 ($duration 秒)..."for i in $(seq 1 "$duration"); dolocal http_code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/ 2>/dev/null || echo "000")local active_conn=$(curl -s http://localhost/nginx_status 2>/dev/null | grep "Active connections" | cut -d':' -f2 | tr -d ' ' || echo "unknown")echo "  时间: ${i}s, HTTP状态: $http_code, 活跃连接: $active_conn"sleep 1done
}# 零停机升级核心
zero_downtime_upgrade() {log "=== 开始零停机升级 ==="local OLD_PID=$(cat "$NGINX_PID_FILE")# 1. 替换二进制文件(不停止服务)log "替换Nginx二进制文件..."cp -f "$NEW_NGINX_BINARY" "$NGINX_BIN" || error "替换二进制文件失败"# 2. 发送USR2信号启动新进程log "发送USR2信号启动新进程..."if ! kill -USR2 "$OLD_PID"; thenerror "发送USR2信号失败"fi# 3. 等待新进程启动log "等待新进程启动..."local wait_count=0while [ $wait_count -lt 15 ]; do  # 增加等待时间if [ -f "${NGINX_PID_FILE}.oldbin" ]; thenlocal NEW_PID=$(cat "$NGINX_PID_FILE")log "新进程启动成功 PID: $NEW_PID"breakfisleep 1((wait_count++))doneif [ $wait_count -eq 15 ]; thenerror "新进程启动超时"fi# 4. 监控服务状态monitor_services 3# 5. 优雅关闭老Worker进程log "优雅关闭老Worker进程..."if ! kill -WINCH "$OLD_PID"; thenwarn "关闭老Worker进程失败,但继续执行..."fi# 6. 等待连接迁移完成log "等待连接迁移完成..."sleep 5# 7. 最终验证verify_upgrade
}# 验证升级结果
verify_upgrade() {log "=== 验证升级结果 ==="local NEW_PID=$(cat "$NGINX_PID_FILE")# 检查新进程是否正常运行if ! ps -p "$NEW_PID" > /dev/null 2>&1; thenerror "新进程运行异常"fi# 全面服务健康检查log "执行服务健康检查..."# HTTP服务检查if ! curl -s -f http://localhost/ > /dev/null 2>&1; thenrollback_upgradeerror "HTTP服务检查失败,已回滚"fi# Nginx状态页检查if ! curl -s http://localhost/nginx_status > /dev/null 2>&1; thenrollback_upgrade  error "Nginx状态页检查失败,已回滚"fi# 端口监听检查if ! ss -lntup | grep -q "nginx.*$NEW_PID"; thenrollback_upgradeerror "端口监听检查失败,已回滚"filocal RUNNING_VERSION=$("$NGINX_BIN" -v 2>&1 | head -n1)log " 升级成功!当前运行版本: $RUNNING_VERSION"# 最终监控monitor_services 2
}# 回滚功能
rollback_upgrade() {log "=== 开始回滚 ==="local OLD_PID_FILE="${NGINX_PID_FILE}.oldbin"if [ -f "$OLD_PID_FILE" ]; thenlocal OLD_PID=$(cat "$OLD_PID_FILE")# 恢复二进制文件if [ -f "$BACKUP_DIR/nginx.old" ]; thencp -f "$BACKUP_DIR/nginx.old" "$NGINX_BIN" || error "回滚二进制文件失败"fi# 发送HUP信号重新加载旧进程log "恢复旧进程..."if kill -HUP "$OLD_PID" 2>/dev/null; then# 等待旧进程恢复sleep 3# 关闭新进程local NEW_PID=$(cat "$NGINX_PID_FILE" 2>/dev/null)if [ -n "$NEW_PID" ] && ps -p "$NEW_PID" > /dev/null 2>&1; thenkill -QUIT "$NEW_PID" 2>/dev/nullfi# 恢复PID文件mv "$OLD_PID_FILE" "$NGINX_PID_FILE"log "回滚完成,服务已恢复至旧版本"elseerror "无法恢复旧进程,需要手动干预"fielseerror "无法回滚,旧PID文件不存在"fi
}# 清理工作
cleanup() {log "=== 清理工作 ==="local OLD_PID_FILE="${NGINX_PID_FILE}.oldbin"if [ -f "$OLD_PID_FILE" ]; thenread -p "是否完全关闭旧Master进程?(y/N): " -n 1 -rechoif [[ $REPLY =~ ^[Yy]$ ]]; thenlocal OLD_PID=$(cat "$OLD_PID_FILE")if kill -QUIT "$OLD_PID" 2>/dev/null; thenrm -f "$OLD_PID_FILE"log "旧Master进程已关闭"elsewarn "关闭旧Master进程失败"fielselog "旧Master进程保持运行,可用于快速回滚"log "如需关闭可手动执行: kill -QUIT \$(cat $OLD_PID_FILE)"fifi# 显示最终状态log "=== 升级完成总结 ==="log "备份位置: $BACKUP_DIR"log "日志文件: $LOG_FILE"log "当前版本: $($NGINX_BIN -v 2>&1 | head -n1)"log "进程状态:"ps -ef | grep nginx | grep -v grep | while read line; dolog "  $line"doneinfo " Nginx零停机平滑升级成功完成!"
}# 主函数
main() {log "Nginx零停机平滑升级脚本启动"log "开始时间: $(date)"# 创建日志文件touch "$LOG_FILE"chmod 600 "$LOG_FILE"check_paramscheck_environmentbackup_currentzero_downtime_upgradecleanuplog "结束时间: $(date)"log "=== Nginx零停机平滑升级成功完成 ==="
}# 信号处理
trap 'error "脚本被用户中断"' INT TERM
trap 'warn "收到异常信号"' HUP QUIT# 执行主函数
main "$@"

脚本使用方式

# 1. 给脚本执行权限
chmod +x /usr/local/bin/nginx_zero_downtime_upgrade.sh# 2. 执行零停机升级
/usr/local/bin/nginx_zero_downtime_upgrade.sh /tmp/nginx-1.24.0# 3. 实时查看升级日志
tail -f /var/log/nginx_upgrade.log# 4. 验证升级结果
nginx -v
systemctl status nginx
curl -I http://localhost

快速部署脚本

#!/bin/bash
# 快速部署Nginx升级脚本SCRIPT_PATH="/usr/local/bin/nginx_zero_downtime_upgrade.sh"echo "部署Nginx零停机升级脚本..."# 创建脚本
cat > $SCRIPT_PATH << 'EOF'
#!/bin/bash
# [上面完整的脚本内容]
EOF# 设置权限
chmod +x $SCRIPT_PATH# 创建日志文件
touch /var/log/nginx_upgrade.log
chmod 600 /var/log/nginx_upgrade.logecho "✅ 脚本部署完成: $SCRIPT_PATH"
echo "使用方法: $SCRIPT_PATH /path/to/new/nginx"

5. 生产环境注意事项

⚠关键检查点

1. 配置兼容性检查
# 必须执行的检查
/path/to/new/nginx -t -c /etc/nginx/nginx.conf# 详细编译参数对比
nginx -V > /tmp/nginx_old_compile.txt
/path/to/new/nginx -V > /tmp/nginx_new_compile.txt
diff
http://www.dtcms.com/a/602724.html

相关文章:

  • 洞头区网站建设收费本地同城服务平台
  • 易语言网站做软件下载上海园区虚拟地址一览表
  • wordpress多站点好吗网页设计居中代码
  • 继荣获GitCode G-Star认证后,数式Oinone入选2025年GitCode百大开源项目
  • 青少年CTF Crypto-factor1
  • 做平面哪个网站的素材最好wordpress一键 centos
  • 商城网站 搭建做小程序的平台
  • 金融网站建设案例仿淘宝网站制作
  • 马和人做人和牛做网站菏泽科技网站建设
  • 三只松鼠网站建设龙华做手机网站
  • fopen函数处理中文路径和内容乱码问题
  • 友点企业网站文化馆 网站 设计
  • 大文件上传全方案:Vue + Node.js 实战
  • SCI精读:基于计算机视觉改进光伏热点和积尘检测:基于现场航拍图像的YOLO模型系统比较
  • 专门做创意桌椅的网站谷歌play商店
  • 怎么查看网站是否做静态化处理0基础如何做网站
  • 基于MATLAB绘制CALIPSO Level 2产品中体积退偏比垂直廓线和频率分布直方图
  • 青岛网站推广哪家效果好搜索引擎营销案例分析
  • 网站网站如何做的充值下载网站开发
  • 做网站公司广州ip地址免费
  • MATLAB中海洋要素计算工具箱解析
  • 网站开发备案需要什么wordpress入门教程(视频)
  • 哪里有网站开发技术怎样优化排名自己网站
  • 重组蛋白基础与技术概述
  • 利用systick定时器获取微秒计数
  • 如何用易语言做网站小说网站的网编具体做哪些工作
  • CAN总线协议:帧格式
  • 企业微信AI怎么用?从智能表格落地看如何提升运营效率
  • 昆明做网站seo南昌公司网站建设
  • 知寰Hybrid RAG:不止于图谱,重新定义GraphRAG的行业智能新范式