Nginx 的 map 指令可基于 $uri 或 $request_uri 动态映射 upstream 名称,需在 http 块定义、location 中用 proxy_pass http://$backend(不带路径),配合 rewrite 实现路径剥离,支持正则匹配与 default 回退。

Nginx 的 map 指令可用于根据请求路径(如 $request_uri 或 $uri)动态设置变量值,再结合 proxy_pass 引用该变量,实现后端 upstream 的灵活切换。关键在于变量必须在 location 外定义、作用域正确、且 proxy_pass 使用变量时不能带 URI 路径。
定义 map 块匹配路径并映射 upstream 名称
在 http 块中使用 map,基于 $uri(标准化路径,不含参数)或 $request_uri(含查询参数)做精确/前缀/正则匹配,将结果赋给自定义变量(如 $backend):
- 用
~开头表示区分大小写的正则匹配,~*表示不区分大小写 - 支持
default设置默认 upstream,避免未匹配时变量为空导致 502 - 路径匹配建议优先用
$uri,更稳定;需匹配带参路径时才考虑$request_uri
示例:
http {
map $uri $backend {
default backend_default;
~^/api/v1/users backend_users;
~^/api/v1/orders backend_orders;
~^/admin backend_admin;
/healthz backend_monitor;
}
upstream backend_default { server 10.0.1.10:8080; }
upstream backend_users { server 10.0.1.20:8080; }
upstream backend_orders { server 10.0.1.30:8080; }
upstream backend_admin { server 10.0.1.40:8080; }
upstream backend_monitor { server 127.0.0.1:9090; }
}
在 location 中通过变量调用对应 upstream
在 server 或 location 块中,用 proxy_pass http://$backend —— 注意:不能加路径后缀(如 http://$backend/api),否则 Nginx 会忽略变量,报错或回退到字面量解析。
- 若需重写路径,用
rewrite或proxy_rewrite配合proxy_pass不带路径的方式 - 确保
$backend变量已定义且拼写一致,Nginx 启动时会校验 upstream 是否存在 - 可配合
proxy_set_header Host $host;等保持原始请求头
示例:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://$backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
处理路径重写与前缀剥离
当不同 upstream 期望的入口路径不一致时(如 /api/v1/users 应转发到 users 服务的 /),需在匹配后剥离前缀:
- 用
rewrite提前改写$uri,再交给map匹配(适合规则简单、统一剥离) - 更推荐:在
location内用rewrite ^/api/v1/(.*)$ /$1 break;+proxy_pass http://backend_users;,但会失去 map 的集中管理优势 - 折中方案:map 中仍按原始路径匹配,再用
proxy_pass+rewrite组合实现路径转换
例如,将 /api/v1/users/xxx 转发到 backend_users 的 /xxx:
location ~ ^/api/v1/users(/|$) {
rewrite ^/api/v1/users(/?)(.*)$ /$2 break;
proxy_pass http://backend_users;
}
验证与调试技巧
配置完成后务必测试,常见问题可通过以下方式定位:
- 运行
nginx -t检查语法;启动后用curl -v http://localhost/xxx观察响应头和状态码 - 开启
error_log /var/log/nginx/error.log debug;查看 map 变量实际取值(需编译时含 debug 日志支持) - 临时添加
add_header X-Backend $backend;到 location,直接从响应头确认路由是否生效 - 注意:map 不支持嵌套或复杂逻辑,超出现有功能建议改用 Lua(via lua-nginx-module)或外部服务路由











