map指令需在http块顶层定义,用于预计算变量映射,支持字符串/正则匹配及多变量拼接,配合upstream实现动态路由与负载均衡。

用 map 指令把转发决策提前“算好”,再让 proxy_pass 直接引用结果变量,就能大幅简化 location 块里的条件判断和重复配置。
map 必须写在 http 块顶层
它不是运行时指令,而是启动时预计算变量的映射规则。不能放在 server 或 location 里,否则 Nginx 启动会报错。正确位置是在 nginx.conf 的 http { } 块内、include mime.types; 之后、include www.conf;(或各站点配置)之前。
- 所有 map 定义对整个 Nginx 实例全局可见,可被任意 server 或 location 复用
- 一个 map 只处理一个源变量(如 $arg_env、$http_x_version、$host),输出一个目标变量(如 $upstream_name)
- 必须设置
default分支,避免未匹配时变量为空导致 proxy_pass 失败
用请求特征映射后端标识
把原本要写在 if 或多层嵌套 location 里的判断逻辑,收拢到 map 中统一维护。比如按请求头选择环境:
map $http_x_env $backend {
default "10.0.1.10:8080";
"prod" "10.0.2.100:8080";
"staging" "10.0.2.101:8080";
"~^canary-.*$" "10.0.2.102:8080";
}
- 字符串匹配走精确值,“staging” 对应 staging 环境
- 正则用
~(区分大小写)或~*(不区分),适合灰度标(如 canary-v1) - 右侧值是纯字符串,可含端口、路径前缀,甚至完整 URL(如
https://api-v2.example.com)
组合多个变量做精细路由
单靠一个变量不够时,可拼接后再映射。例如结合域名与路径决定租户集群:
map "$host:$request_uri" $tenant_upstream {
default "default_cluster";
"~*^client-a\.example\.com:/api/v1/.*$" "client_a_v1";
"~*^client-b\.example\.com:/api/v2/(orders|users)/.*$" "client_b_v2_$1";
}
- 用冒号拼接避免歧义,
$1引用正则捕获组,生成client_b_v2_orders这类动态名称 - 配合 upstream 块定义同名集群:
upstream client_a_v1 { server 192.168.1.10:8080; } - location 中只需一行:
proxy_pass http://$tenant_upstream;
配合 upstream 实现真正负载均衡
map 本身不提供健康检查、权重或失败重试。若需这些能力,应把 map 输出的值作为 upstream 名称,而非直接写 IP+端口:
- 定义:
map $arg_env $upstream_name { default "app_default"; "v2" "app_v2"; } - 声明:
upstream app_v2 { server 10.0.3.20:8080 weight=3; server 10.0.3.21:8080 max_fails=2; } - 转发:
location / { proxy_pass http://$upstream_name; } - 这样既保留了 map 的动态路由能力,又复用了 upstream 的成熟负载策略

















