Nginx的map指令不直接路由,而是将客户端特征映射为结构化变量,多维度路由依赖多个map块协同与变量闭环使用;需选对源变量、分层提取、嵌套降级、严格语法约束。

Nginx 的 map 指令本身不执行路由,而是把客户端特征“翻译”成结构化变量;真正实现多维度路由分发,靠的是多个 map 块协同 + 变量闭环使用(比如传给 proxy_pass 或 root)。关键不在单个 map 多复杂,而在如何分层提取、组合判断、安全兜底。
选对源变量:IP、Header、路径、UA 都可作为第一维依据
每个 map 必须基于一个稳定字符串型变量,常见选择包括:
-
客户端真实 IP:直连用
$remote_addr;经 CDN 或代理时,先配set_real_ip_from和real_ip_header X-Forwarded-For,再用$realip_remote_addr -
请求头字段:如
$http_x_env(环境标识)、$http_x_canary_id(灰度 ID),注意 Header 名自动转小写,含下划线需开启underscores_in_headers on -
路径或方法:用
$uri做精确前缀匹配(如/api/v2/),或$request_method区分读写流量 -
User-Agent:映射为
$is_mobile、$ua_category等布尔或分类变量,用于终端适配
嵌套 map 实现“优先级+降级”逻辑
单一维度容易冲突或覆盖,多维度需明确先后顺序。典型做法是:高优特征先映射,未命中则交由次优特征兜底。
例如,先看灰度 Header,再 fallback 到 UA 或 IP 段:
map $http_x_canary_id $route_stage {
"" "fallback";
default "canary";
}
<p>map $http_user_agent $fallback_stage {
~curl "dev";
~Postman "staging";
~iPhone|Android "mobile";
default "prod";
}</p><p>map $route_stage $upstream_name {
"canary" "upstream_canary";
"fallback" $fallback_stage; # 这里引用另一个 map 变量
}注意:$fallback_stage 输出值必须与 upstream 名完全一致(如 upstream_dev),且所有 map 都要有 default,否则变量为空会导致 proxy_pass 失败返回 502。
变量闭环使用:让 map 结果真正驱动转发或响应
map 生成的变量只是“开关”,必须接入具体指令才能生效:
-
动态后端路由:在
location中写proxy_pass http://$upstream_name/(末尾斜杠不能少,且$upstream_name必须对应已定义的upstream块) -
静态资源路径切换:配合
root /var/www/$device/;,需提前建好对应目录结构 -
缓存策略差异化:用
proxy_cache_key "$host$uri$is_mobile";,让移动端和桌面端缓存分离 -
响应头注入或限流:如
add_header X-Route-Stage $route_stage;或结合limit_req zone=$route_stage
必须遵守的硬约束,否则配置不生效
map 不是普通指令,它有严格语法和位置要求:
- 所有
map块必须写在http { }最外层,且在server、upstream定义之前;放进站点配置或嵌套在server里会报unknown directive "map" - 每个
map必须带default分支,推荐设为最常用或最安全的值(如"prod"、"global") - 输出值要能被下游指令直接消费:upstream 名不支持短横线(
backend-v2❌),只接受字母、数字、下划线(backend_v2✅) - 正则匹配用
~(大小写敏感)或~*(忽略大小写),不支持 PCRE 高级语法,避免过度复杂



















