Nginx通过正则提取子域名租户标识、map映射后端、透传至网关动态发现三种方式实现多租户动态路由,支持泛域名SSL与自动证书管理。

Nginx 实现多租户架构下的动态后端路由,核心在于从请求域名中提取租户标识,并据此决定转发目标。这不是靠手动为每个租户写一个 server 块,而是用正则捕获 + 变量映射 + 条件代理的方式,让配置具备可扩展性。
基于子域名提取租户名并路由
Nginx 支持在 server_name 中使用正则表达式命名捕获组,把子域名部分直接提取为变量:
server {
listen 80;
server_name ~^(?<tenant>[^.]+)\.example\.com$;
location / {
proxy_pass http://backend-$tenant;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}这里 (?<tenant>[^.]+)</tenant> 会匹配 tenant1.example.com 中的 tenant1,并赋值给 $tenant 变量。proxy_pass 后接 http://backend-$tenant,就等效于转发到名为 backend-tenant1 的 upstream。
你需要提前定义对应的 upstream:
upstream backend-tenant1 {
server 10.0.1.10:8000;
}
upstream backend-tenant2 {
server 10.0.1.11:8000;
}
upstream backend-default {
server 127.0.0.1:8000;
}使用 map 指令做更灵活的后端映射
当租户与后端地址关系复杂(比如租户名和集群 IP 不一一对应,或需 fallback),推荐用 map 指令预定义映射表:
map $host $upstream_backend {
default backend-default;
tenant1.example.com backend-tenant1;
tenant2.example.com backend-tenant2;
~^([a-z0-9]+)\.example\.com backend-dynamic;
}然后在 server 块中直接引用:
server {
listen 80;
server_name ~^([a-z0-9]+)\.example\.com$ example.com;
location / {
proxy_pass http://$upstream_backend;
proxy_set_header Host $host;
# 其他 header...
}
}注意:map 必须放在 http 块顶层,不能嵌套在 server 内;它在请求解析早期执行,性能优于 if。
支持泛域名 + 动态集群发现(进阶)
若租户数量极大或需自动扩缩容,可将 $tenant 透传给后端应用,由应用层查询服务注册中心(如 Consul、Nacos)获取真实后端地址,Nginx 仅做轻量代理:
location / {
proxy_pass http://127.0.0.1:8001; # 转发给本地路由网关
proxy_set_header X-Tenant $tenant;
proxy_set_header Host $host;
}这个本地网关(如用 Python/FastAPI 写)收到 X-Tenant 后,查数据库或配置中心,再做二次代理。这种方式解耦更强,适合云原生环境。
SSL 与证书适配要点
-
通配符证书
*.example.com可覆盖所有子域名,必须在对应server块中加载:ssl_certificate /etc/ssl/certs/example.com_wildcard.pem; ssl_certificate_key /etc/ssl/private/example.com_wildcard.key;
若启用 SNI,确保 Nginx 版本 ≥ 1.15.9,且 OpenSSL 支持;旧版本可能无法正确分发不同证书。
对自定义域名租户(如
clientbrand.com),需配合 ACME 自动化工具(如 Certbot 或 Nginx Proxy Manager)按需签发并热加载证书。
不复杂但容易忽略


















