Nginx作为反向代理和负载均衡器在后端架构中占有不可替代的位置。upstream模块提供了多种负载均衡算法和健康检查机制,合理配置后端节点池、感知故障节点并自动调整请求分发策略,是保证服务高可用的关键环节。本文围绕Nginx upstream模块的算法选择、主动健康检查配置和故障恢复策略展开。
Nginx upstream负载均衡算法对比与选型策略
Nginx开源版提供三种内置负载均衡算法:
Round Robin(轮询):默认算法,按权重依次将请求分发到后端节点。适合后端节点性能相近的场景。
upstream backend {
server 10.0.1.10:8080 weight=3;
server 10.0.1.11:8080 weight=2;
server 10.0.1.12:8080 weight=1;
# 请求按3:2:1比例分发
}
Least Connections(最少连接):将请求分发到当前活跃连接数最少的节点。适合请求处理时间差异较大的场景(如混合API路由)。
upstream backend {
least_conn;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
IP Hash(源地址哈希):根据客户端IP计算哈希值固定分发到特定后端节点,实现会话保持。注意:当后端节点数量变化时,哈希分布会重新打散,导致部分会话失效。
upstream backend {
ip_hash;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
选型建议:无状态的REST API服务首选least_conn,能在不同节点负载差异时自动均衡;WebSocket或SSE等长连接场景必须使用least_conn或ip_hash,轮询会导致新连接堆积在一个节点;有session状态的服务用ip_hash,但建议配合分布式session存储作为更可靠的方案。
Nginx被动健康检查与故障节点自动摘除配置
Nginx开源版内置被动健康检查(passive health check),通过max_fails和fail_timeout参数实现:在fail_timeout时间窗口内,如果某个节点失败次数达到max_fails,该节点被标记为不可用,持续fail_timeout时长后重新尝试。
upstream backend {
server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.12:8080 max_fails=3 fail_timeout=30s backup;
}
server {
listen 80;
location /api/ {
proxy_pass http://backend;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
proxy_connect_timeout 3s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
}
proxy_next_upstream定义触发重试的错误类型:error表示连接失败,timeout表示读写超时,http_500/502/503/504表示后端返回对应的5xx状态码。proxy_next_upstream_tries限制最大重试次数,避免请求在多个故障节点间连锁转发导致延迟放大。
backup参数标记备份节点:仅当所有主节点都不可用时才接收流量。适合配置一台低配备用机器作为兜底,返回降级响应。
Nginx Plus主动健康检查与开源替代方案
Nginx Plus(商业版)支持主动健康检查,通过health_check指令定期向后端发送探测请求,无需等待真实请求失败即可发现故障:
# Nginx Plus 主动健康检查
upstream backend {
zone backend 64k;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
server {
location /api/ {
proxy_pass http://backend;
health_check interval=5s fails=3 passes=2 uri=/health;
health_check_timeout 2s;
}
}
开源版的替代方案是使用nginx_upstream_check_module模块(淘宝开源),编译安装后提供与Plus类似的主动健康检查能力:
upstream backend {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
# 主动健康检查
check interval=5000 rise=2 fall=3 timeout=2000 type=http;
check_http_send "GET /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
# 健康检查状态页面
location /upstream_status {
check_status;
access_log off;
allow 10.0.0.0/8;
deny all;
}
}
rise=2表示连续2次检查成功才恢复节点,fall=3表示连续3次失败才标记不可用,避免网络抖动导致的误判。
Nginx upstream慢启动与故障恢复平滑过渡配置
故障节点恢复后,如果立即接收全额流量,大量请求涌入刚刚重启的服务可能导致二次过载(thundering herd问题)。Nginx Plus的slow_start参数实现渐进式流量恢复:
upstream backend {
server 10.0.1.10:8080 slow_start=30s;
server 10.0.1.11:8080 slow_start=30s;
server 10.0.1.12:8080 slow_start=30s;
}
开源版可通过lua脚本实现等价逻辑,利用ngx.shared.dict记录节点恢复时间,在前30秒内按比例降低该节点的权重:
# nginx.conf
lua_shared_dict node_recovery 10m;
upstream backend {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
server {
location /api/ {
access_by_lua_block {
local recovery = ngx.shared.node_recovery
local key = ngx.var.upstream_addr
if key then
local recover_time = recovery:get(key)
if recover_time then
local elapsed = ngx.time() - recover_time
if elapsed < 30 then
-- 30秒内以一定概率直接返回503跳过该节点
if math.random() < (30 - elapsed) / 30 * 0.5 then
return ngx.exit(503)
end
end
end
end
}
proxy_pass http://backend;
}
}
实际生产中,配合Consul或Nacos等服务注册中心,通过lua-resty-upstream-healthcheck库实现动态节点发现、主动健康检查和自动摘除的一体化方案,是Nginx开源版在微服务场景下的主流架构选择。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/nginx-fan-xiang-dai-li-fu-zai-jun-heng-suan-fa-yu-upstream/