Nginx可通过map指令实现基于请求头的动态路由:将$http_x_service映射为$backend_upstream变量,再在proxy_pass中引用该变量指向对应upstream,支持正则匹配、空值兜底和默认分支,无需if即可高效完成条件转发。

Nginx 本身不支持基于请求头(Header)内容的“动态路由”(如根据 X-Env: prod 自动匹配后端集群),但可通过 map 指令 + 变量 + upstream 实现高效、声明式的条件路由,效果等同于动态转发。
用 map 指令提取 Header 值并映射为上游名称
这是核心技巧:将请求头字段(如 X-Service 或 X-Region)映射为预定义的 upstream 名称,后续 proxy_pass 直接引用变量即可。
在 http 块中定义:
map $http_x_service $backend_upstream {
default backend_default;
"user-api" backend_user;
"order-api" backend_order;
"payment-api" backend_payment;
}说明:
• $http_x_service 是 Nginx 内置变量,自动获取请求头 X-Service 的值(小写且带下划线);
• 映射结果存入自定义变量 $backend_upstream,值为 upstream 名称;
• 匹配不中时走 default 分支,避免 502。
定义多个 upstream 实现服务隔离
每个 upstream 对应一组真实后端服务,支持健康检查、负载均衡等:
upstream backend_default {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
<p>upstream backend_user {
server 10.0.2.20:8080;
server 10.0.2.21:8080;
}</p><p>upstream backend_order {
server 10.0.3.30:8080 weight=3;
server 10.0.3.31:8080;
}在 location 中使用变量完成条件转发
在 server 或 location 块中直接引用 $backend_upstream:
server {
listen 80;
server_name api.example.com;
<pre class="brush:php;toolbar:false;">location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://$backend_upstream; # ← 关键:变量名即 upstream 名
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}}
注意:
• proxy_pass 后必须以 / 结尾或不带路径(如 http://$backend_upstream/),否则变量不生效;
• 不支持在 proxy_pass 中拼接路径和变量(如 http://$backend_upstream/v1),需靠 rewrite 或后端处理。
进阶:Header 不存在或为空时兜底处理
若希望 Header 缺失时跳过 map 或强制走默认,可增强 map 条件:
map $http_x_service $backend_upstream {
"" backend_default; # 空字符串
"~^user.*" backend_user; # 正则匹配(开头为 user)
"~^order.*" backend_order;
default backend_default;
}还可结合 if(仅限部分上下文)做前置拦截,但推荐优先用 map —— 更安全、更高效、支持正则和默认值。


















