Administrator
发布于 2025-11-06 / 4 阅读
0
0

Nginx深入详解之upstream分配方式

本文汇总并校正 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

可配合 weightbackupmax_failsfail_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;
}

可结合 twoleast_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_methodstream 模块里有 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;
}
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_connrandom two least_conn

  • 简单粘性:ip_hash;更复杂的粘性(cookie、一致性哈希)考虑第三方或 Nginx Plus。

  • 静态/缓存命中:需要 URI 一致性分配时,用第三方 hash $request_uri 或在上游缓存层实现一致性。

  • 高并发 + 不均匀键空间:第三方哈希算法(如 murmur)分布更均匀;注意这是第三方指令。


评论