1. 为什么需要平滑升级Nginx
作为运维工程师,最头疼的就是服务升级导致业务中断。记得去年我们电商大促期间,因为一个紧急安全补丁需要重启Nginx,导致整整3分钟的服务不可用,直接损失了上百万订单。这种惨痛教训让我下定决心要掌握Nginx的平滑升级技术。
Nginx的平滑升级(Hot Upgrade)是指在不停止服务的情况下完成版本更新。其核心原理是利用Nginx的多进程架构:
- 主进程(Master Process)负责管理
- 工作进程(Worker Process)处理请求
- 新旧版本可以共存的特点
2. 升级前的关键准备工作
2.1 环境检查清单
在开始升级前,我通常会做以下检查:
- 当前版本确认:
nginx -v - 编译参数备份:
nginx -V(注意是大写V) - 配置文件校验:
nginx -t - 现有进程查看:
ps -ef | grep nginx
重要提示:一定要记录原有的configure参数!我有次升级后才发现SSL模块丢失,就是因为没备份编译参数。
2.2 下载新版本源码包
从官网下载时要注意:
bash复制wget https://nginx.org/download/nginx-1.28.0.tar.gz
sha256sum nginx-1.28.0.tar.gz # 校验完整性
2.3 编译环境准备
不同系统依赖略有差异:
- CentOS:
yum install -y gcc make pcre-devel openssl-devel zlib-devel - Ubuntu:
apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev
3. 详细升级步骤解析
3.1 编译新版本
bash复制tar zxvf nginx-1.28.0.tar.gz
cd nginx-1.28.0
./configure --prefix=/usr/local/nginx \ # 必须与原路径一致
--with-http_ssl_module \ # 保持原有模块
--with-http_gzip_static_module
make # 注意不要make install!
3.2 替换二进制文件
关键操作顺序:
- 备份旧二进制:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old - 停止旧worker:
kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid) - 替换新二进制:
cp objs/nginx /usr/local/nginx/sbin/nginx - 测试新版本:
/usr/local/nginx/sbin/nginx -t
3.3 完成升级过程
bash复制# 优雅关闭旧worker
kill -WINCH $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
# 确认新版本运行
ps -ef | grep nginx
# 可选:彻底关闭旧master
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
4. 实战中的避坑指南
4.1 常见问题排查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 新worker不启动 | 编译参数不一致 | 重新检查configure参数 |
| 出现502错误 | 动态模块不兼容 | 检查--add-module路径 |
| 配置文件报错 | 新版本语法变更 | 查阅官方升级日志 |
4.2 必须知道的几个信号量
USR2:启动新master进程WINCH:优雅关闭worker进程QUIT:优雅退出master进程HUP:重新加载配置
4.3 回滚方案
如果升级后发现问题:
- 恢复旧二进制:
mv /usr/local/nginx/sbin/nginx.old /usr/local/nginx/sbin/nginx - 重启旧master:
kill -HUP $(cat /usr/local/nginx/logs/nginx.pid.oldbin) - 关闭新进程:
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid)
5. 升级后的验证要点
我通常会进行以下测试:
- 基础功能测试:
bash复制
curl -I http://localhost openssl s_client -connect localhost:443 -tls1_2 - 性能对比:
bash复制
ab -n 10000 -c 100 http://localhost/ - 日志检查:
bash复制tail -f /usr/local/nginx/logs/error.log
对于生产环境,建议先在测试环境验证以下场景:
- 长连接保持
- WebSocket连接
- 大文件上传下载
- 负载均衡后端健康检查
6. 版本差异注意事项
从1.26.3升级到1.28.0需要特别注意:
- 新增的
$ssl_curve变量可能影响某些日志格式 - 废弃的
ssl指令需要改为listen ... ssl - HTTP/2的优先级处理算法有优化
- 对于使用regex的location,性能有显著提升
建议完整阅读官方ChangeLog:
code复制http://nginx.org/en/CHANGES-1.28
http://nginx.org/en/CHANGES-1.27
7. 自动化升级方案
对于需要批量升级的场景,我常用的Ansible Playbook示例:
yaml复制- hosts: nginx_servers
tasks:
- name: Download nginx
get_url:
url: https://nginx.org/download/nginx-1.28.0.tar.gz
dest: /tmp/nginx-1.28.0.tar.gz
- name: Extract source
unarchive:
src: /tmp/nginx-1.28.0.tar.gz
dest: /tmp/
remote_src: yes
- name: Configure
command: ./configure {{ nginx_configure_args }}
args:
chdir: /tmp/nginx-1.28.0
- name: Make
command: make
args:
chdir: /tmp/nginx-1.28.0
- name: Backup binary
command: cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
- name: Install new binary
command: cp objs/nginx /usr/local/nginx/sbin/nginx
args:
chdir: /tmp/nginx-1.28.0
- name: Send USR2 signal
command: kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
- name: Send WINCH signal
command: kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin`
8. 监控与告警配置
升级后需要新增的监控项:
- 进程树监控:
bash复制ps -ef | grep nginx | grep -v grep | wc -l - 版本一致性检查:
bash复制
/usr/local/nginx/sbin/nginx -v | grep -q 1.28.0 - 特殊指标采集:
code复制nginx_status_active_connections nginx_status_handled_requests
推荐Prometheus的监控配置示例:
yaml复制- job_name: 'nginx'
metrics_path: '/status'
static_configs:
- targets: ['localhost:8080']
9. 性能调优建议
升级后可以尝试的新参数:
nginx复制http {
# 新增的线程池配置
thread_pool default threads=32 max_queue=65536;
# 优化后的epoll配置
epoll_events 512;
# 1.28版本增强的SSL缓存
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets on;
# 新的内存分配策略
tcp_nopush on;
tcp_nodelay on;
sendfile_max_chunk 512k;
}
10. 延伸思考:架构层面的高可用
虽然平滑升级能解决单节点问题,但对于真正的零停机升级,还需要考虑:
- 负载均衡器的健康检查配置
- 多AZ部署和流量切换
- 蓝绿发布策略
- 客户端重试机制配置
一个完整的升级窗口期操作流程:
- 从负载均衡摘除待升级节点
- 等待现有连接耗尽(通常2个心跳周期)
- 执行平滑升级
- 运行冒烟测试
- 重新加入负载均衡
- 观察5分钟监控指标
