nginx 不原生支持按任意 http header 值动态负载分发,但可通过 map 模块将 header(如 x-region)映射为 upstream 名变量,再在 proxy_pass 中引用该变量实现多集群路由;各 upstream 可独立配置轮询、权重或 least_conn 等策略,并支持基于 $http_x_request_id 的一致性哈希调度(需 nginx ≥ 1.11.6)。

Nginx 本身不直接支持“按任意 HTTP Header 字段值做负载分发”的原生调度策略(比如 proxy_pass 动态跳转到不同 upstream),但可以通过 map 模块 + 多 upstream 分组 + 条件 proxy_pass 的组合方式,间接实现基于 Header 的路由与负载均衡逻辑。
核心思路:用 map 提取 Header 值,映射到 upstream 名称
利用 Nginx 的 map 指令,将请求中的某个 Header(如 X-Region、X-Tenant 或 User-Agent)的值,映射为一个变量(如 $backend_group),再在 proxy_pass 中引用该变量指向对应 upstream 块。每个 upstream 可独立配置自己的负载策略(轮询、加权、least_conn 等)。
示例:根据 X-Region Header 将流量分发到不同区域集群:
http {
# 定义区域到 upstream 名称的映射
map $http_x_region $backend_group {
default "default_backend";
"cn" "cn_backend";
"us" "us_backend";
"eu" "eu_backend";
}
<pre class="brush:php;toolbar:false;"># 各区域后端集群(各自独立负载均衡)
upstream cn_backend {
server 10.0.1.10:8080 weight=3;
server 10.0.1.11:8080;
}
upstream us_backend {
server 10.0.2.10:8080;
server 10.0.2.11:8080 weight=2;
}
upstream eu_backend {
server 10.0.3.10:8080;
server 10.0.3.11:8080;
}
upstream default_backend {
server 10.0.0.10:8080;
}
server {
listen 80;
location / {
proxy_pass http://$backend_group; # 关键:动态 upstream 名
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}}
进阶:Header 值做哈希分发(一致性路由)
若需同一 Header 值(如 X-Request-ID)始终打到同一台后端(类似会话保持),可用 hash 指令配合 upstream 内的 hash 调度,但注意:hash 必须在 upstream 块内声明,且不能直接 hash 外部变量。可行做法是先用 map 提取 Header,再在 upstream 内使用 hash $arg_x_request_id —— 但更稳妥的是改用 $http_x_request_id(Nginx 1.11.6+ 支持):
- 确保 Nginx 版本 ≥ 1.11.6(推荐 ≥ 1.20)
- 在 upstream 中启用 hash,并指定 header 变量:
upstream backend_by_id {
hash $http_x_request_id consistent; # 一致性哈希,保证相同 ID 总落到同一台
server 10.0.4.10:8080;
server 10.0.4.11:8080;
server 10.0.4.12:8080;
}
然后在 server 块中固定使用该 upstream(无法动态切换,适用于单一 Header 路由场景)。
注意事项与限制
-
map 是静态映射:不能执行正则捕获或复杂逻辑,如需提取子串(如
X-Version: v2.1→ 取v2),需搭配map+ 正则(~*)或升级到 OpenResty 使用 Lua 处理 -
proxy_pass 不支持变量拼接 URL:只能写成
http://$var,不能写http://$var/api;路径需由 location 控制 -
Header 名称自动转小写并用下划线替代短横:例如
X-User-ID对应变量为$http_x_user_id - 若 Header 为空或不存在,
$http_*变量值为空字符串,map 的default分支会生效
替代方案:OpenResty + Lua(高灵活性场景)
当 Header 解析逻辑复杂(如 JSON 解析、多级嵌套字段判断、调用外部服务鉴权),纯 Nginx 配置难以胜任。此时可引入 OpenResty,在 access_by_lua_block 中读取 ngx.var.http_x_custom,动态设置 ngx.ctx.upstream_name,再通过 balancer_by_lua_block 实现完全自定义的后端选择逻辑。但这已超出标准 Nginx 范畴,属于扩展开发范畴。











