Nginx 生产环境平滑升级指南:从二进制热部署到健康检查配置
在Nginx生产环境中实现不停机(平滑)升级版本的关键,是充分利用其支持热替换(Hot Replacement)的特性。以下是详细操作流程和注意事项:
一、关键原理
- 主进程:管理配置、绑定端口、控制子进程
- 工作进程:处理实际请求(
worker_processes
) - 信号控制:
USR2
:启动新版本二进制WINCH
:优雅停止旧工作进程QUIT
:完全退出旧主进程
二、详细操作步骤
1. 预检与备份
# 备份配置文件、二进制文件和日志
cp -r /usr/local/nginx /usr/local/nginx_backup_$(date +%F)
# 查看当前版本和编译参数
nginx -V
2. 编译新版本(以这次静态编译为例)
# 下载新版源码
wget https://tengine.taobao.org/download/tengine-3.1.0.tar.gz
tar -xvf ./tengine-3.1.0.tar.gz
cd tengine-3.1.0
# 使用docker创建临时环境,这个退出docker时就会自动删除
docker run -it --rm -v $(pwd):/work alpine:latest sh
# 安装必要依赖
apk add --no-cache gcc g++ make perl linux-headers curl gnupg pcre-dev zlib-dev openssl-dev openssl-libs-static git
# 下载zlib依赖
wget https://zlib.net/zlib-1.3.1.tar.gz
tar xf zlib-1.3.1.tar.gz
# 设置编译参数,--prefix=/opt/nginx 表示默认运行目录为/opt/nginx,如tms
./configure --prefix=/opt/nginx --with-http_v2_module --with-http_ssl_module --add-module=./modules/ngx_http_upstream_check_module --with-cc-opt='-static-libgcc' --with-ld-opt='-static' --with-zlib=/work/tengine/zlib-1.3.1
# 也可以配置时保持与原版一致(注意输出参数)
# ./configure <原版参数> --with-http_stub_status_module...
# 四线程编译
make -j4
# 编译完的二进制在./objs/nginx
3. 替换二进制文件(热部署)
# 替换二进制文件(不要make install!)
cp objs/nginx /usr/sbin/nginx
4. 发送信号启动热更新
# 检测新版本是否正确(重要)
nginx -t
# 向旧主进程发送USR2信号(启动新实例)
kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid)
# 此时会生成新旧两个主进程PID文件:
# /usr/local/nginx/logs/nginx.pid # 新主进程
# /usr/local/nginx/logs/nginx.pid.oldbin # 旧主进程
5. 逐步关闭旧进程
# 发送WINCH信号让旧进程停止接受新连接,处理完现有请求后退出
kill -WINCH $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
# 观察旧进程状态(此时旧进程还在但不处理请求)
ps aux | grep nginx
6. 最终切换确认
# 如果新版本运行正常,彻底退出旧主进程
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
# 如果发现问题需要回滚,立即发送HUP重启旧进程,TERM新进程:
kill -HUP $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
kill -TERM $(cat /usr/local/nginx/logs/nginx.pid)
三、关键注意事项
-
编译参数一致性:
- 使用
nginx -V
获取旧版本的编译参数,确保模块(如--with-http_ssl_module
)和依赖库一致。
- 使用
-
验证环节:
- 升级前在生产环境的测试沙盒中验证:
nginx -t -c /usr/local/nginx/conf/nginx.conf
- 升级前在生产环境的测试沙盒中验证:
-
依赖项兼容性:
- 检查新版本是否依赖更高的OpenSSL、PCRE等库版本。
-
会话保持:
- 当使用长连接(如WebSocket)时,确保升级前通过配置
worker_shutdown_timeout
合理超时。
- 当使用长连接(如WebSocket)时,确保升级前通过配置
-
回滚预案:
# 快速回滚方法 cp /usr/local/nginx/sbin/nginx_old /usr/local/nginx/sbin/nginx kill -USR2 <新主进程PID> # 启动旧版本
-
监控指标:
- 升级后监控:
nginx -s status
(需配置stub_status
模块)- 系统负载、错误日志(
tail -f /usr/local/nginx/log/error.log
)
- 升级后监控:
四、NGINX配置相关
本次升级配置修改部分主要是使用了 ngx_http_upstream_check_module
模块,用来自动检查 upstream
节点的可用性,配置文档可参考:https://tengine.taobao.org/document_cn/http_upstream_check_cn.html
- 添加自动替换参数,以
oms
服务为例:
upstream omsserver{
server 172.16.3.134:8088 max_fails=30 weight=1;
server 172.16.3.134:8089 max_fails=30 weight=1; #上面这两行不动,添加下面三行
check interval=10000 rise=2 default_down=false fall=3 timeout=1000 type=http;
check_http_send "GET /kj/keepAlive HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
配置格式为:
Syntax: check
interval=milliseconds [fall=count] [rise=count] [timeout=milliseconds] [default_down=true|false] [type=tcp|http|ssl_hello|mysql|ajp] [port=check_port]
interval
:向后端发送的健康检查包的间隔。
rise
(rise_count): 如果连续成功次数达到rise_count,服务器就被认为是up。
default_down
: 设定初始时服务器的状态,如果是true,就说明默认是down的,如果是false,就是up的。默认值是true,也就是一开始服务器认为是不可用,要等健康检查包达到一定成功次数以后才会被认为是健康的。
fall
(fall_count): 如果连续失败次数达到fall_count,服务器就被认为是down。
timeout
: 后端健康请求的超时时间。
type
:健康检查包的类型,现在支持以下多种类型:
tcp
:简单的tcp连接,如果连接成功,就说明后端正常。ssl_hello
:发送一个初始的SSL hello包并接受服务器的SSL hello包。http
:发送HTTP请求,通过后端的回复包的状态来判断后端是否存活。mysql
: 向mysql服务器连接,通过接收服务器的greeting包来判断后端是否存活。ajp
:向后端发送AJP协议的Cping包,通过接收Cpong包来判断后端是否存活。
我们使用的配置 check interval=10000 rise=2 default_down=false fall=3 timeout=1000 type=http;
含义为:每10s检测一次,如果连续两次都成功说明服务正常,nginx启动后默认所有节点都是成功的状态,连续测试失败三次表明服务不可用,检测检测请求超1s没响应就是失败。
check_http_send "GET /kj/keepAlive HTTP/1.0\r\n\r\n";
和 check_http_expect_alive http_2xx http_3xx;
含义为使用 GET
请求 /kj/keepAlive
,如果返回2xx和3xx状态码说明服务正常,一般情况下建议使用 HEAD
请求,因为 HEAD
方法只请求服务器返回 HTTP 头部信息,而 不返回响应体 (body),对服务器没有压力,oms
这个是使用 HEAD
一直报错才换成 GET
。
- 添加节点状态查看配置:
location /status {
auth_basic "Restricted Area";
auth_basic_user_file /usr/local/nginx/auth/htpasswd; #添加访问密码
check_status;
access_log off;
allow 10.0.0.0/8; #设置允许的网段,除了10.0.0.0/8和172.16.0.0/16其他都不允许访问
allow 172.16.0.0/16;
deny all;
}
认证账号密码使用 htpasswd
命令创建,指定用户名后需要输入两次密码:
htpasswd -c ./htpasswd ks # 创建用户名为ks
可以使用 http://example.com/status
输入密码查看状态,同时支持不同的格式输出,默认是html格式:
/status?format=html
/status?format=csv
/status?format=json
认证界面:
节点监控界面:
通过遵循上述步骤,可以在生产环境中实现Nginx版本的无缝升级,确保服务持续可用。