跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何利用 map 指令根据请求路径动态切换不同的后端 Upstream

Nginx 的 map 指令可基于 $uri 或 $request_uri 动态映射 upstream 名称,需在 http 块定义、location 中用 proxy_pass http://$backend(不带路径),配合 rewrite 实现路径剥离,支持正则匹配与 default 回退。 Nginx 的
map
指令可用于根据请求路径(如
$request_uri
或
$uri
)动态设置变量值,再结合
proxy_pass
引用该变量,实现后端 up stream 的灵活切换。关键在于变量必须在
location
外定义、作用域正确、且
proxy_pass
使用变量时不能带 URI 路径。 定义 map 块匹配路径并映射 u ps tream 名称 在
http
块中使用
map
,基于
$uri
(标准化路径,不含参数)或
$request_uri
(含查询参数)做精确/前缀/正则匹配,将结果赋给自定义变量(如
$backend
): 用
~
开头表示区分大小写的正则匹配,
~*
表示不区分大小写 支持
default
设置默认 upstream,避免未匹配时变量为空导致 502 路径匹配建议优先用
$uri
,更稳定;需匹配带参路径时才考虑
$request_uri
示例: 稿定在线PS PS软件网页版 下载
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)或外部服务路由

相关文章