map指令是nginx中用于动态变量映射的核心工具,基于源变量值预计算新变量,供if、proxy_pass等指令使用,支持灰度发布、多租户路由、时段限流等场景,需在http块定义且依赖已解析变量。

map 指令是 Nginx 中实现动态变量映射的核心工具,它不直接处理请求,而是根据某个源变量的值,预先计算并生成一个新的变量值。这个新变量后续可被 if、proxy_pass、return、set 等指令使用,从而支撑灵活的流量调度策略。
用 map 实现灰度发布(按用户 ID 或 Cookie 分流)
常见场景是将 5% 的真实用户导流到新版本服务。不能靠随机数(不可复现),而应基于稳定标识做哈希取模。比如从 Cookie 中提取用户 ID,再映射为一个分组标识:
配置示例:
map $cookie_uid $backend_group {
default "v1";
~^(\d+) "$1";
}
map $backend_group $upstream_server {
default "backend-v1";
~^[02468]$ "backend-v2"; # 偶数 ID 走 v2
}
说明:第一层 map 提取 UID 数字部分;第二层 map 判断该数字末位是否为偶数,决定后端分组。这样相同 UID 总是命中同一版本,满足灰度一致性要求。
结合 Host 和 URI 实现多租户路由
当多个客户共用一个域名(如 app.example.com),需根据请求路径前缀或子域名识别租户,并路由到对应集群:
配置示例:
map $host $tenant_id {
~^([a-z0-9]+)\.example\.com$ $1;
default "default";
}
map $request_uri $service_path {
~^/api/v1/(users|orders)/(.*)$ "/$1/$2";
~^/api/v2/(products|payments)/(.*)$ "/$1/$2";
default "/";
}
upstream tenant-$tenant_id {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
说明:通过 host 提取租户名构造 upstream 名称,再用 request_uri 映射出标准化的服务路径,配合 proxy_pass http://tenant-$tenant_id$service_path; 即可完成精准路由。
基于请求头和时间做条件限流或降级
map 可以配合内置变量(如 $time_iso8601)做时段控制,也可解析自定义请求头(如 X-Env)实现环境感知:
配置示例:
map $http_x_env $route_to {
"staging" "staging-backend";
"prod" "prod-backend";
default "fallback-backend";
}
map $time_iso8601 $is_offpeak {
"~^20[0-9]{2}-[0-1][0-9]-[0-3][0-9]T(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]" "0";
default "1";
}
# 在 server 块中:
if ($is_offpeak = "1") {
set $route_to "maintenance-backend";
}
说明:白天高峰时段走正常后端,凌晨自动切到维护页;同时优先尊重客户端传入的环境标识,便于测试人员手动覆盖。
注意事项与避坑指南
map 是在请求初始化阶段执行的,因此只能引用 Nginx 已解析出的变量(如 $arg_、$cookie_、$http_、$time_* 等),不能调用函数或执行 shell 命令。
- map 块必须定义在
http上下文中,不能放在 server 或 location 内 - 正则匹配时,建议用
~(区分大小写)或~*(忽略大小写),避免误匹配 - 未匹配到任何规则时,会使用 default 值;若没写 default,变量值为空字符串,可能引发后续逻辑异常
- map 不支持嵌套调用,但可通过多级 map 链式传递结果,注意变量依赖顺序
掌握 map 的本质——它是变量的“编译期”映射器,不是运行期脚本引擎。把复杂判断提前转化为简单变量,再交由其他指令消费,这才是高效、可靠的做法。











