nginx 通过 http 块中 map 指令将请求头(如 $http_x_backend_route)映射为 upstream 变量,再由 proxy_pass 引用实现动态路由;需设 default 值、正则前缀 ~、严格匹配 upstream 名称,并在 location 中使用 http://$backend_upstream 转发。

用 map 指令根据请求头动态选 upstream,核心是把请求头值映射成一个变量,再让 proxy_pass 引用它。这个过程必须在 http 块里完成,不能写在 server 或 location 里。
定义 map 规则匹配请求头
Nginx 会自动把请求头(比如 X-Backend-Route)转成小写加下划线格式的变量,如 $http_x_backend_route。用它作为源变量,映射出目标 upstream 名称:
- 每条规则按顺序匹配,遇到第一个满足的就停止
- 字符串匹配直接写值,正则匹配要加
~前缀(如~^canary-) - 必须设
default,否则未匹配时变量为空,导致 502 错误 - 示例:
map $http_x_backend_route $backend_upstream {
default backend_default;
"v2" backend_v2;
"legacy" backend_legacy;
~^canary- backend_canary;
}
声明对应的 upstream 块
map 输出的变量名(如 $backend_upstream)必须对应一个已定义的 upstream 块名,不能是纯 URL 字符串(除非你明确写成 "http://10.0.1.10:8080",但不推荐):
- 每个 upstream 可独立配置健康检查、权重、ip_hash 等
- 名称要和 map 中右侧值完全一致(大小写、下划线都不能错)
- 示例:
upstream backend_default { server 10.0.1.10:8080 max_fails=3; }
upstream backend_v2 { server 10.0.1.20:8080; }
upstream backend_canary { server 10.0.1.40:8080; }
在 location 中使用变量转发
只需在 location 块里调用已定义的变量即可,不需要额外逻辑:
-
proxy_pass http://$backend_upstream;—— 注意协议+变量,结尾不加路径 - 如果后端需要原始请求头,加上
proxy_set_header X-Backend-Route $http_x_backend_route; - 避免在
proxy_pass后拼接 URI(如/api),否则会覆盖客户端原始路径
验证与调试要点
上线前建议用 curl 手动触发不同请求头,观察是否路由到预期节点:
- 测试命令:
curl -H "X-Backend-Route: v2" http://your.domain/api - 查看 Nginx error log(开启
debug级别)可确认变量是否被正确计算 - 注意请求头名称大小写:浏览器发
X-Backend-Route,Nginx 内部是$http_x_backend_route - 若用正则匹配版本号(如
X-API-Version: 2.5),规则写成~^2\.,注意点号要转义











