Nginx不支持原生嵌套upstream,但可通过map+变量、split_clients、rewrite+多location等组合实现分层路由:先按请求特征映射到上游组名,再由proxy_pass动态转发至对应upstream,完成“第一层路由→第二层负载均衡”语义。

Nginx 本身不支持“负载均衡组的嵌套”或“分层调度”这种原生语法(比如 upstream 套 upstream),但可以通过合理组合 upstream、map、split_clients、变量控制和多级 proxy_pass 配合 rewrite 或 if(谨慎使用)来模拟出分层、条件化、动态路由的效果。关键在于把“分层逻辑”从配置结构上转移到请求处理流程中。
用 map + 变量实现逻辑分层
通过 map 指令根据请求特征(如域名、路径前缀、Header、IP 地址段)将流量映射到不同 upstream 名称,再在 proxy_pass 中引用该变量,达到“第一层路由 → 第二层负载均衡”的效果。
示例:
map $http_x_region $backend_group {
default "us_servers";
"cn" "cn_servers";
"eu" "eu_servers";
}
<p>upstream us_servers {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}</p><p>upstream cn_servers {
server 10.0.2.10:8080 weight=3;
server 10.0.2.11:8080;
}</p><p>upstream eu_servers {
server 10.0.3.10:8080;
server 10.0.3.11:8080 max_fails=2 fail_timeout=10s;
}</p><p>server {
listen 80;
location / {
proxy_pass <a href="https://www.php.cn/link/093d559928d57fc466488f5176506e29">https://www.php.cn/link/093d559928d57fc466488f5176506e29</a>;
proxy_set_header Host $host;
}
}说明:这里 $backend_group 是运行时确定的 upstream 名,Nginx 会按其内容选择对应 upstream 块进行真实转发——实现了“按区域分组 → 组内轮询/加权”的两层调度语义。
用 split_clients 实现灰度/分桶分层
适用于需要按用户 ID、Cookie 或随机哈希做固定分流(如 5% 流量进新集群),属于“第一层分流 → 第二层 LB”的典型场景。
示例(按用户 cookie 分流):
split_clients "$cookie_uid" $upstream_name {
5% "canary_backend";
* "stable_backend";
}
<p>upstream canary_backend {
server 192.168.10.100:8080;
}</p><p>upstream stable_backend {
server 192.168.10.200:8080;
server 192.168.10.201:8080;
}</p><p>location /api/ {
proxy_pass <a href="https://www.php.cn/link/75e4374aa05da63dcfe5cd0e9d4e9504">https://www.php.cn/link/75e4374aa05da63dcfe5cd0e9d4e9504</a>;
}注意:split_clients 不支持正则或复杂条件,适合简单哈希分流;它在请求初始化阶段执行,性能开销极小。
用 rewrite + 多 location 实现路径驱动的嵌套路由
当不同路径需导向不同 upstream,且某些路径还需进一步按参数/头信息细分时,可结合 rewrite 设置内部变量,再由后续 location 或 map 捕获处理。
- 先用
location ~ ^/v1/匹配大类 - 用
set $route_key "$arg_env-$http_x_service";构造复合键 - 再用
map $route_key $final_upstream映射到具体 upstream - 最终
proxy_pass http://$final_upstream
这种方式把“分层”逻辑显式拆解为可读、可维护的步骤,避免嵌套配置带来的可维护性问题。
注意事项与限制
- upstream 名不能是动态拼接字符串(如
"group_"$var),只能是完整变量名(如$var),且该变量值必须精确匹配已定义的 upstream 名 - 不支持在 upstream 块中引用其他 upstream;所有“嵌套”都必须在 proxy_pass 阶段通过变量间接实现
- if 在 location 中慎用(有陷阱),优先用 map 和 split_clients 这类无副作用指令
- 健康检查(health_check)需在每个 upstream 内单独配置,无法跨组统一管理


















