Nginx作为反向代理服务器,通过upstream模块实现后端节点间的流量分发。负载均衡配置不只是轮询分发请求,还涉及健康检查、会话保持、故障转移等生产级需求。在高并发场景下,upstream的调度算法和连接参数直接影响后端服务的稳定性和响应速度。
Nginx upstream负载均衡算法配置
Nginx原生支持四种负载均衡算法:轮询(默认)、加权轮询、ip_hash(按客户端IP哈希)、least_conn(最少连接数)。每种算法适用于不同的业务场景。
# nginx.conf - upstream基础配置
upstream backend_api {
# 加权轮询:性能强的节点分配更多请求
server 10.0.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.1.11:8080 weight=2 max_fails=3 fail_timeout=30s;
server 10.0.1.12:8080 weight=1 max_fails=3 fail_timeout=30s;
# 备用节点:主节点全部不可用时启用
server 10.0.1.20:8080 backup;
# 连接保持:减少TCP握手开销
keepalive 32;
keepalive_timeout 60s;
keepalive_requests 1000;
}
# ip_hash:同一客户端IP固定访问同一后端节点
upstream backend_session {
ip_hash;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
# least_conn:优先分发到当前连接数最少的节点
upstream backend_compute {
least_conn;
server 10.0.1.10:8080 weight=3;
server 10.0.1.11:8080 weight=2;
}
server {
listen 80;
server_name api.example.com;
location /api/ {
proxy_pass http://backend_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 10s;
}
}
被动健康检查与故障自动剔除
Nginx内置的被动健康检查通过max_fails和fail_timeout参数实现。当某节点在fail_timeout时间内失败次数达到max_fails,Nginx自动将其标记为不可用,在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 {
listen 80;
location / {
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;
}
}
# 验证健康检查效果
# curl http://10.0.1.10:8080/health -> 502
# Nginx自动将请求转发到10.0.1.11
# tail -f /var/log/nginx/error.log
# 可看到 "upstream timed out" 和自动切换日志
主动健康检查:nginx_upstream_check_module
upstream backend {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
# 主动健康检查
check interval=3000 rise=2 fall=3 timeout=2000 type=http;
# interval=3000: 每3秒检查一次
# rise=2: 连续2次成功标记为健康
# fall=3: 连续3次失败标记为不健康
check_http_send "GET /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
# 健康检查状态页
location /upstream_status {
check_status;
access_log off;
allow 10.0.0.0/8;
deny all;
}
location / {
proxy_pass http://backend;
}
}
会话保持方案:sticky cookie与一致性哈希
# 基于Lua的一致性哈希(开源方案)
lua_package_path "/usr/local/lib/lua/?.lua;;";
upstream backend {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
keepalive 32;
}
server {
listen 80;
location /api/ {
access_by_lua_block {
local chash = require "resty.chash"
local nodes = {
["10.0.1.10:8080"] = 100,
["10.0.1.11:8080"] = 100,
["10.0.1.12:8080"] = 100,
}
local men = chash:new({nodes = nodes})
local key = ngx.var.arg_user_id or ngx.var.remote_addr
local node = men:find(key)
ngx.var.upstream_addr = node
}
proxy_pass http://backend;
}
}
故障排查:upstream连接超时与502诊断
# 1. 检查后端服务是否存活
curl -v http://10.0.1.10:8080/health
# 连接拒绝 -> 后端进程未启动或端口未监听
# 超时 -> 防火墙阻断或后端过载
# 2. 检查Nginx错误日志定位具体原因
tail -f /var/log/nginx/error.log | grep upstream
# "connect() failed (111: Connection refused)" -> 后端未启动
# "upstream timed out" -> 后端响应过慢
# "no live upstreams" -> 所有后端节点被剔除
# 3. 系统层面排查
ss -s | grep TIME-WAIT
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_max_tw_buckets=5000
# 4. 检查文件描述符限制
ulimit -n
# worker_connections 10240 -> 需要ulimit -n至少10240
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
# 5. Nginx访问日志添加upstream响应时间
log_format upstream_log '$remote_addr - $request_time '
'$upstream_response_time $upstream_addr $status';
access_log /var/log/nginx/access.log upstream_log;
# $upstream_response_time > 30s 说明后端处理过慢
Nginx负载均衡配置需要结合业务特点选择调度算法。无状态API服务用加权轮询,计算密集型任务用least_conn,有状态服务配置会话保持。生产环境务必配置主动健康检查和连接保持,避免单节点故障引发雪崩。监控upstream响应时间和错误率,结合自动扩缩容策略应对流量波动。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/nginx-fan-xiang-dai-li-yu-fu-zai-jun-heng-pei-zhi-shi-zhan/