nginx原生weight不支持按请求头条件路由,需用map提取header值并结合独立upstream分组实现:先用map匹配authorization头设定$upstream_group变量,再分别定义high_auth和default upstream,最后在location中通过proxy_pass http://$upstream_group完成精准分流。

Nginx 原生的 weight 参数本身不支持按请求头内容做条件性路由,它只在 upstream 的加权轮询(weighted round-robin)中全局生效,无法感知或匹配 Authorization、X-Auth-Token 等 header。
要让高权重节点「专门处理带特定授权头的请求」,必须绕过纯 weight 机制,改用 基于请求特征的显式分流 + 独立 upstream 分组。
✅ 正确做法:用 map + split_clients 或 if + proxy_pass 指向不同 upstream
1. 先按请求头区分流量类型
用 map 提取并标记目标分组:
map $http_authorization $upstream_group {
~*^Bearer\s+[a-f0-9]{32}$ "high_auth";
~*^Basic\s+.*$ "basic_auth";
default "default";
}
✅ 支持正则匹配;
$http_authorization自动小写,无需手动转;匹配成功即赋值,后续可直接引用。
2. 定义两套独立 upstream(关键)
-
upstream_high_auth:只含高性能节点,设高权重(如weight=10) -
upstream_default:含全部节点,按常规能力配权(如weight=3,weight=1,weight=1)
upstream upstream_high_auth {
server 10.0.2.10:8080 weight=10;
server 10.0.2.11:8080 weight=8; # 只放可信、高配、专用于认证流量的机器
}
upstream upstream_default {
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. 在 location 中根据变量选择 upstream
location /api/ {
proxy_pass http://$upstream_group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 防止 map 失效时 fallback 到默认组
proxy_next_upstream error timeout http_500;
}
⚠️ 注意:不能在
proxy_pass中写http://upstream_$upstream_group—— Nginx 不支持变量拼接 upstream 名;必须提前定义好全名,并用$upstream_group直接引用。
❌ 常见误区(别这么干)
- 试图在
upstream块里用if或map动态改weight:语法不支持,nginx -t 直接报错 - 把
weight=0和 header 匹配混用:weight=0是静态摘除,不响应任何请求,也无法“按需启用” - 依赖
ip_hash或least_conn同时想用 weight:前者忽略 weight,后者完全不读 weight
? 进阶建议:结合健康检查与动态隔离
若高权重点仅服务特定 token 类型,建议额外加固:
- 给
upstream_high_auth单独配严苛健康检查:server 10.0.2.10:8080 weight=10 max_fails=1 fail_timeout=10s;
- 在应用层返回
401或403时,用proxy_next_upstream转发到upstream_default降级处理(需后端配合返回明确错误码)
这样配置后,带 Authorization: Bearer xxx 的请求会稳定打到 upstream_high_auth,其他请求走默认组——既满足业务隔离,又保留各组内部的加权调度能力。











