Nginx负载均衡算法由upstream块中首个有效调度指令决定,proxy_pass仅负责将请求转发至该upstream;默认为轮询,ip_hash、least_conn、hash等算法互斥且前者优先,加权轮询属轮询变体,ip_hash下weight失效。

proxy_pass 本身不决定负载均衡算法,它只是把请求“发给谁”的指令;真正决定怎么分发请求的,是 upstream 块里写的调度策略。也就是说,upstream 定义了“池子怎么干活”,proxy_pass 只是“把活交给这个池子”。优先级不是靠 proxy_pass 写法决定的,而是由 upstream 块中**最先出现的有效调度指令**决定。
upstream 中算法声明的生效顺序
upstream 块内可以写多个指令(如 ip_hash、least_conn、hash $request_uri),但 Nginx 只认第一个有效的负载均衡算法指令,后面的同类指令会被忽略。注意:不是所有指令都互斥,但算法类指令之间有明确的覆盖关系。
- ip_hash、least_conn、hash、fair、url_hash 这些都是互斥的算法开关,谁写在最前面,就用谁
- weight、max_fails、fail_timeout 等参数属于服务器配置项,不影响算法选择,可共存
- 如果没有显式写任何算法,默认启用轮询(round-robin)
- 如果写了 ip_hash,就自动禁用 weight(权重失效),因为 IP 哈希必须保证同一 IP 总打到同一台,加权会破坏一致性
常见组合与实际效果对比
以下配置片段能清晰体现优先级逻辑:
-
轮询(默认):
upstream app { server 192.168.1.10:8080; server 192.168.1.11:8080; }→ 不写任何算法,就是轮询 -
加权轮询:
upstream app { server 192.168.1.10:8080 weight=3; server 192.168.1.11:8080 weight=1; }→ 仍属轮询范畴,只是带权重 -
IP 哈希优先于 weight:
upstream app { ip_hash; server 192.168.1.10:8080 weight=5; server 192.168.1.11:8080 weight=1; }→ weight 被忽略,只按客户端 IP 分配 -
least_conn 优先于轮询:
upstream app { least_conn; server a; server b; }→ 即使 a、b 没写 weight,也按当前连接数最少的选 -
hash $request_uri 优先于 ip_hash:
upstream app { hash $request_uri; ip_hash; server a; server b; }→ 实际生效的是 hash $request_uri,ip_hash 不起作用
location + proxy_pass 如何触发 upstream 算法
proxy_pass 的值必须精确匹配 upstream 块的名字(如 http://myapp),Nginx 才会把该 location 下所有请求交由对应 upstream 处理。关键点:
- proxy_pass 后面不能带路径(如
http://myapp/api),否则会触发重写行为,可能绕过 upstream 的负载逻辑 - 如果 proxy_pass 指向一个域名而非 upstream 名,Nginx 就不会走你定义的算法,而是直接 DNS 解析后做简单转发
- upstream 名称区分大小写,且不能含下划线以外的特殊字符(建议全小写+字母数字)
- 每个 server 块里可定义多个 upstream,但一个 proxy_pass 只能绑定一个
调试与验证算法是否生效
光看配置不够,得验证实际流量走向:
- 用
curl -H "Host: test.com" http://nginx-ip/多次请求,配合后端日志或 tcpdump 查看目标 IP 是否符合预期 - 开启 Nginx stub_status 模块(需编译时启用),访问
/nginx_status可看到各 upstream server 的 request 数、active 连接数等 - 临时在 upstream 中加入
server 127.0.0.1:8080 down;或max_fails=1 fail_timeout=5s;,观察是否触发剔除和恢复 - 对 ip_hash,换不同公网 IP(如手机热点)访问,确认后端固定;对 url_hash,反复请求同一 URL,确认后端不变











