least_conn本身不支持多租户隔离,需为每个租户单独定义upstream块并启用least_conn,通过物理分池实现隔离;再结合header或路径识别路由至对应租户池,并配置独立健康检查、连接限制与日志审计确保隔离有效。

least_conn 本身不直接支持“多租户隔离调度”,它只是一个单 upstream 内部的节点选择算法,作用范围仅限于当前 upstream 块内的健康后端。要实现多租户隔离下的 least_conn 调度,核心思路是:为每个租户单独定义独立的 upstream 块,并在各自块中启用 least_conn —— 隔离靠“物理分池”,调度靠“池内 least_conn”。
1. 每个租户独占一个 upstream + least_conn
不能把所有租户后端混在一个 upstream 里再靠 header 或路径区分,否则 least_conn 会跨租户争抢连接数,失去隔离意义。
正确做法是为 tenant-a、tenant-b 各建一个 upstream:
-
tenant-a 的专用池(带 least_conn):
upstream tenant_a_backend {
least_conn;
server 10.0.1.10:8080 max_conns=600;
server 10.0.1.11:8080 max_conns=600;
keepalive 32;
} -
tenant-b 的专用池(同样启用 least_conn):
upstream tenant_b_backend {
least_conn;
server 10.0.2.20:8080 max_conns=1200;
server 10.0.2.21:8080 max_conns=1200;
keepalive 32;
}
注意:max_conns 可按租户资源配额设置,避免某租户耗尽全部连接容量。
2. 请求路由到对应租户池
不能靠全局 least_conn 分发,必须先识别租户身份,再 proxy_pass 到其专属 upstream。
推荐两种安全识别方式(需配合日志审计):
-
Header 识别(推荐):用
map提前映射租户 ID → upstream 名,非法值默认拦截
map $http_x_tenant_id $upstream_pool {
default "";
"a" tenant_a_backend;
"b" tenant_b_backend;
}
server {
location /api/ {
if ($upstream_pool = "") { return 400; }
proxy_pass http://$upstream_pool;
# 其他 proxy_* 配置…
}
} -
路径前缀识别(兼容旧系统):
location ^~ /t/a/ {
rewrite ^/t/a/(.*)$ /$1 break;
proxy_pass http://tenant_a_backend;
}
location ^~ /t/b/ {
rewrite ^/t/b/(.*)$ /$1 break;
proxy_pass http://tenant_b_backend;
}
3. 租户级连接与健康控制
每个 upstream 必须独立配置健康检查和连接限制,防止故障或过载扩散:
-
健康检查独立生效:每个
server行加max_fails=2 fail_timeout=15s,故障只剔本租户池节点 -
连接数硬隔离:用
limit_conn控制单租户总并发(例如基于$http_x_tenant_idzone) -
超时策略按租户定制:不同租户接口 P99 差异大时,在对应 location 中设不同
proxy_read_timeout
4. 验证是否真正隔离调度
上线后重点确认三点,缺一不可:
- 访问
/nginx_status(需开启stub_status),分别查看tenant_a_backend和tenant_b_backend下各 server 的 Active connections 是否各自均衡、互不影响 - 在后端机器上执行
ss -s | grep ESTAB,确认连接只出现在对应租户的 IP 池中,无跨池连接 - 检查 access log,确保每条记录都含准确的租户标识(如
$http_x_tenant_id),且未出现 fallback 到 default 或空值


















