本文汇总并校正 Nginx 的 upstream 负载均衡策略,用简洁示例说明场景选择与注意事项。
内置分配方式(HTTP 模块)
默认轮询(round robin)
upstream backend {
server 192.168.1.101:8888;
server 192.168.1.102:8888;
server 192.168.1.103:8888;
}不需要额外指令,按顺序分配到各 server。
可配合 weight、backup、max_fails、fail_timeout 等参数。
加权轮询(通过
weight参数)
upstream backend {
server 192.168.1.101 weight=1;
server 192.168.1.102 weight=2;
server 192.168.1.103 weight=3;
}适合后端性能不一致的场景。
最少连接(
least_conn)
upstream backend {
least_conn;
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
}将新请求分配给当前连接数最少的后端。
适合长连接或响应时间差异明显的场景。
随机(
random)
upstream backend {
random two least_conn;
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
}可结合 two 与 least_conn 进行“两择一择优”。
IP 哈希(
ip_hash)
upstream backend {
ip_hash;
server 192.168.1.101:7777;
server 192.168.1.102:8888;
server 192.168.1.103:9999;
}基于客户端 IP 做粘性分配,适合简单会话粘性。
受真实 IP 获取方式影响,处于反代/LB 后需配置 real_ip(见下文)。
与 weight 共用时意义有限,建议简单使用。
第三方或商业版特性
fair(第三方模块 upstream_fair)
upstream backend {
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
fair; # 需要编译第三方模块
}按后端响应时间(RT)分配,RT 小的优先。
使用方式:在
upstream中加入fair;。
URL/自定义哈希(第三方模块,如 upstream_hash)
upstream backend {
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
hash $request_uri; # 需要第三方模块或商业版支持
hash_method crc32; # 同上
}基于
$request_uri等键做(一致性)哈希分配;适合缓存命中、避免同资源跨节点切换。示例中的
hash_method crc32;属于第三方指令(非官方内置)。提示:官方开源版 HTTP upstream 不内置
hash/hash_method;stream模块里有hash key [consistent](TCP/UDP),HTTP 的一致性哈希/sticky 更全面的特性在 Nginx Plus 提供。
server 参数与健康策略
基本语法:
server address [parameters]
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}address:主机名/域名/IP/unix:/path.sock,可含端口。
常用参数:
down:标记后端停用。backup:备用后端,仅在主后端不可用时分配请求。weight=<n>:权重,默认 1。max_fails=<n>和fail_timeout=<time>:在时间窗口内失败次数阈值,超过则暂不选择此后端。
代理端示例与纠错
基本反代:
location /router/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; # 注意是 X-Real-IP(中划线)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}单域名反代(仅一个合法业务域名):
location /test/router {
proxy_pass http://test.yl.66huyu.cn/router;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}WebSocket/长连接反代(带安全提示):
location /zone {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 86400;
# 危险:直接信任用户参数可能导致开放代理风险
# proxy_pass http://$arg_host:$arg_port;
# 建议:通过允许列表映射为安全目标
# 例如:map 定义允许的主机与端口,再在此处使用
proxy_pass http://$target_upstream;
}允许列表映射(示例):
客户端请求 :wss://www.ooxx.com/zone?host=134.175.33.159&port=8888
nginx自动会把参数加arg_前缀,代理向ttp://$arg_host:$arg_port,则客户端自动就连向了http://134.175.33.151:8888
http {
# 将 host:port 映射到安全的 upstream 名称
map "$arg_host:$arg_port" $target_upstream {
default ""; # 默认拒绝
"134.175.33.159:8888" backend_a; # 允许的目标
"134.175.33.151:8888" backend_b;
}
upstream backend_a { server 134.175.33.159:8888; }
upstream backend_b { server 134.175.33.151:8888; }
server {
listen 443 ssl;
# ... SSL 配置略
location /zone {
if ($target_upstream = "") { return 403; }
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 仅转发 /zone,并清空查询参数
proxy_pass http://$target_upstream/zone?;
}
}
}在反代/LB 场景下获取真实客户端 IP
若 Nginx 位于第二层(后面还有 LB/CDN/反代),需配置 real ip:
http {
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 172.16.0.0/12;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}只信任实际的上游来源网段或 IP,避免用户伪造头部;配置后
$remote_addr才能表示真实客户端 IP,ip_hash/限流/日志才会准确。
选择建议与场景归纳
一般后端:默认轮询 +
weight即可。长连接/不同负载:优先
least_conn或random two least_conn。简单粘性:
ip_hash;更复杂的粘性(cookie、一致性哈希)考虑第三方或 Nginx Plus。静态/缓存命中:需要 URI 一致性分配时,用第三方
hash $request_uri或在上游缓存层实现一致性。高并发 + 不均匀键空间:第三方哈希算法(如
murmur)分布更均匀;注意这是第三方指令。