nginx 中 map 指令用于根据请求特征动态生成变量,配合 proxy_pass 实现条件式反向代理;map 必须定义在 http 块内,proxy_pass 引用变量时不可拼接路径,需变量本身含完整地址,并设 default 值兜底。

在 Nginx 中,map 指令本身不执行转发,但它能根据请求特征(如域名、路径、Header、参数等)动态生成变量值;再配合 proxy_pass,就能实现基于业务逻辑的条件式反向代理。关键在于:用 map 提前计算目标上游地址(或端口、路径前缀等),再在 location 块中引用该变量完成转发。
用 map 提取并映射业务标识
map 必须定义在 http 块内,不能放在 server 或 location 中。常见做法是提取请求中的可区分字段,映射为后端服务标识:
- 按 Host 区分租户:
map $host $backend_service {
default "http://internal-api-default";
tenant-a.example.com "http://internal-api-tenant-a:8080";
tenant-b.example.com "http://internal-api-tenant-b:8081";
} - 按请求头路由灰度流量:
map $http_x_release_version $upstream_addr {
~^v2\. "http://api-v2-backend";
default "http://api-v1-backend";
}(支持正则匹配,注意~^开头) - 按 URL 参数识别环境:
map $arg_env $target_api {
dev "http://dev-api.internal";
staging "http://staging-api.internal";
default "http://prod-api.internal";
}
在 location 中安全调用 proxy_pass
proxy_pass 支持变量,但有重要限制:若 proxy_pass 值含变量,**不能带 URI 路径尾缀**(即不能写成 proxy_pass $backend_service/v1;),否则会报错或行为异常。正确写法是让变量完整包含协议、主机、端口和可选路径:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- ✅ 正确(变量含完整地址):
location /api/ {
proxy_pass $target_api;
proxy_set_header Host $host;
} - ❌ 错误(变量后拼接路径):
proxy_pass $target_api/v1; # 语法错误 - ? 补救方案:若需重写路径,用
rewrite配合proxy_pass的“无路径”形式:
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass $target_api;
}
结合 set_by_lua* 实现更复杂逻辑(进阶)
纯 map 不支持多条件组合、查数据库、调用外部 API 等。此时可引入 ngx_http_lua_module,用 set_by_lua_block 替代部分 map 场景:
- 例如:根据用户 token 解析出 tenant_id,再查 Redis 获取对应后端地址:
set_by_lua_block $upstream_addr {
local token = ngx.var.http_authorization
if not token then return "http://fallback" end
local tenant = require "jwt".verify(token).tenant_id
local redis = require "resty.redis":new()
redis:connect("127.0.0.1", 6379)
return redis:get("tenant:"..tenant..":upstream") or "http://default"
} - 注意:Lua 变量需在
server或location内定义,且要确保模块已编译启用(OpenResty 推荐)。
务必验证与兜底
动态转发易因变量未定义、映射缺失、上游不可达导致 502/503。应主动防御:
- 所有
map块必须设default值,避免变量为空; - 在
proxy_pass前加判断(用if不推荐,可用try_files或 Lua); - 配置
proxy_next_upstream error timeout http_502;自动重试; - 用
log_format记录实际使用的$upstream_addr,便于排障。










