nginx的upstream模块本身不支持正则调度,但可通过map指令基于$request_uri等变量匹配正则,动态映射到预定义upstream组,再由proxy_pass调用,实现按规则分流。

Nginx 的 upstream 模块本身不支持基于正则表达式的调度逻辑。它的调度算法(如 rr、least_conn、ip_hash、hash $arg_xxx 等)作用于请求的固定变量(如 $remote_addr、$request_uri、$args、$host),而非运行时对 URI 或 header 进行动态正则匹配并据此选后端。
但你可以通过 组合 map 指令 + upstream 分组 + proxy_pass 动态变量,间接实现“按正则规则分流到不同 upstream 组”的效果。这不是 upstream 内部做正则调度,而是由 Nginx 在 proxy 阶段前,用 map 提前计算出目标 upstream 名称。
✅ 正确做法:用 map 实现基于正则的 upstream 路由
1. 定义多个 upstream 组
upstream api_v1 {
server 10.0.1.10:8000;
server 10.0.1.11:8000;
}
upstream api_v2 {
server 10.0.2.10:8000;
server 10.0.2.11:8000;
}
upstream admin_backend {
server 10.0.3.10:9000;
}
2. 使用 map 根据 $request_uri(或其他变量)匹配正则,映射到 upstream 名
map $request_uri $backend_upstream {
default "api_v1";
~^/api/v1/.* "api_v1";
~^/api/v2/[a-z]+/id/\d+ "api_v2";
~^/admin/(login|logout|dashboard) "admin_backend";
~*\.(js|css|png|jpg|gif)$ "api_v1"; # 静态资源也走 api_v1
}
⚠️ 注意:
map块必须在http { }级别定义,不能放在server或location内。
3. 在 location 中使用动态 proxy_pass
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://$backend_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
✅ 此时 Nginx 会先执行 map 匹配,确定 $backend_upstream 的值(如 "api_v2"),再将请求代理到 http://api_v2 对应的 upstream 组。
❌ 常见错误(不可行)
- 在
upstream { }块里写if或正则判断 → 语法不支持,配置会报错 - 在
proxy_pass中直接写正则路径,如proxy_pass http://backend~/v2/→ Nginx 不识别这种写法 - 试图让
ip_hash或hash $request_uri执行正则提取 →hash只接受完整变量或简单表达式,不支持~匹配
? 补充:若需更复杂路由逻辑(如多条件、header+uri组合)
可叠加多个 map:
map $http_user_agent $is_mobile {
"~*Android|iPhone" 1;
default 0;
}
map $is_mobile:$request_uri $route_to {
"1:/api/" "mobile_api";
"0:/api/" "desktop_api";
default "fallback";
}
然后 proxy_pass http://$route_to;
? 小结关键点
- upstream 本身无正则调度能力,这是设计限制
-
map是 Nginx 提供的轻量级运行时变量映射机制,支持 PCRE 正则,是实现“规则路由”的标准方案 - 所有
map变量必须在http块中声明,且只能用于后续指令(如proxy_pass、fastcgi_pass)的字符串插值 - 动态
proxy_pass http://$var要求$var的值必须是已定义的 upstream 名(大小写敏感,不含协议或路径)
不复杂但容易忽略。











