在多租户系统的运维优化与用户体验升级中,将传统的 "IP + 租户参数" 访问模式重构为 "二级域名" 直接访问,是提升系统易用性、品牌辨识度与运维效率的关键举措。本文结合实际落地经验,完整拆解多租户系统域名化改造的全流程,涵盖需求分析、核心设计思路、技术实现方案及前后端适配要点,为同类改造提供可复用的实践参考。
文章目录
-
- 一、改造背景与核心诉求
-
- [1. 改造前的访问痛点](#1. 改造前的访问痛点)
- [2. 改造核心目标](#2. 改造核心目标)
- 二、系统基础架构
- 三、改造核心设计思路
- 四、具体改造实现
-
- [1. Nginx 配置改造(核心)](#1. Nginx 配置改造(核心))
- [2. 前端适配改造](#2. 前端适配改造)
-
- [2.1 核心改造逻辑](#2.1 核心改造逻辑)
- [2.1 核心改造逻辑](#2.1 核心改造逻辑)
- 2.2.核心改造点:
- [2.3.效果验证(请求 / 响应头示例):](#2.3.效果验证(请求 / 响应头示例):)
- 五、改造验证
- 六、总结
一、改造背景与核心诉求
1. 改造前的访问痛点
系统原采用「IP 地址 + URL 参数」的租户区分方式,访问链路存在明显短板:
-
访问格式示例:
- 000000 租户:
http://192.168.0.14?tenant=000000 - oracle 租户:
http://192.168.0.14?tenant=oracle
- 000000 租户:
-
核心问题:
① 访问路径不直观,用户需记忆 IP 和租户参数,体验差;
② URL 参数易泄露、易篡改,存在租户隔离风险;
③ 无法通过域名实现租户级别的访问管控与品牌化展示。
补充说明:改造前前端需在请求头(Header)中手动设置
tenantId标识当前租户,增加了前端逻辑复杂度。
2. 改造核心目标
构建「二级域名 + 自动租户解析」的访问体系,同时保障兼容性:
-
新访问格式示例:
- 000000 租户:
http://000000.mf.com - oracle 租户:
http://oracle.mf.com
- 000000 租户:
-
核心要求:
① 域名访问时自动解析租户标识,无需手动传参;
② 完全兼容原有「IP + 参数」访问方式,无感知切换;
③ 租户标识透传链路闭环,保证前后端数据一致性。
二、系统基础架构
改造前的系统架构为后续改造提供了基础支撑:
- 部署架构:独立部署的多租户微服务集群,前端通过 Nginx 反向代理承接所有请求;
- 核心逻辑:系统核心依赖请求中的
tenantURL 参数(或 Header 中的tenantId)完成租户上下文识别; - 改造基础:Nginx 作为流量入口,具备域名解析、请求头注入的天然优势,是本次改造的核心载体。
三、改造核心设计思路
本次改造的核心是构建「域名解析 → 租户透传 → 前后端适配 → 一致性校验」的闭环链路,整体流程如下:

改造的核心是 "域名解析 - 租户透传 - 前后端适配" 闭环,整体流程如下:
- 前端发起二级域名请求(如
oracle.mf.com); - Nginx 解析请求域名,提取二级域名作为租户标识(
oracle),并将其写入请求头X-Tenant-Id; - Nginx 将请求转发至后端微服务,后端从
X-Tenant-Id获取租户信息; - Nginx 将请求转发处理完请求后,在响应头中返回
X-Tenant-Id告知前端当前生效的租户标识; - 前端适配:兼容 IP + 参数、二级域名两种访问方式,统一从响应头获取并缓存租户标识。
关键设计原则:
- 优先级原则:域名解析的租户标识优先级高于 URL 参数 / 手动请求头,保证域名访问的准确性;
- 闭环原则:租户标识从 Nginx 注入请求头,最终通过响应头回传前端,形成完整校验闭环;
- 兼容原则:不修改原有核心业务逻辑,仅在流量入口层做适配,降低改造风险。
四、具体改造实现
1. Nginx 配置改造(核心)
通过 Nginx 的 map 指令解析二级域名,结合 proxy_set_header 和 add_header透传租户标识,同时兼容原有 IP 访问方式。
conf
# 域名不固定,随机的时,直接定义对应关系
#map $host $tenant_id {
# 固定键值对:域名 → 租户ID
# a1.mf.com "oracle";
# a2.mf.com "tidb";
# a2.xx.mf.com "clickhouse";
# a3.mf.com "mysql";
# default "";
#}
# 1. 定义域名-租户映射规则:从请求域名中提取二级域名作为租户ID
map $host $tenant_id {
# 默认值:匹配不到二级域名时(如IP访问)置空
default "";
# 正则命名捕获:匹配 *.mf.com 格式域名,捕获前缀作为租户ID
# 正则说明:[a-zA-Z0-9-]+ 覆盖数字、字母、短横线的租户ID场景,适配常见租户标识规则
~^(?<tenant>[a-zA-Z0-9-]+)\.mf\.com$ $tenant;
}
server {
listen 80;
# 匹配所有 mf.com 后缀的二级域名
server_name *.mf.com;
location / {
# 2. 优先级处理:域名解析的租户ID > 原有请求头中的租户ID(IP访问时)
set $proxy_tenant_id $http_x_tenant_id;
if ($tenant_id) {
set $proxy_tenant_id $tenant_id;
}
# 3. 将租户ID写入请求头,透传给后端服务
proxy_set_header X-Tenant-Id $proxy_tenant_id;
# 4. 将租户ID写入返回请求头,透传给前端服务
add_header X-Tenant-Id $proxy_tenant_id;
# 5. 基础转发配置:保留客户端真实信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 6. 转发至后端微服务集群(替换为实际地址)
proxy_pass http://backend_service_cluster;
}
}
关键说明:
-
map指令:将域名解析逻辑抽离,避免在location中重复正则匹配,提升 Nginx 处理效率; -
always关键字:确保所有响应(包括 4xx/5xx 错误)都携带X-Tenant-Id,前端无需额外处理异常场景; -
正则范围:
[a-zA-Z0-9-]+覆盖主流租户 ID 命名规则,可根据业务扩展(如支持下划线:[a-zA-Z0-9-_]+)。
2. 前端适配改造
前端核心目标是「兼容两种访问方式 + 统一租户标识来源」,无需修改业务逻辑,仅需优化请求 / 响应拦截逻辑:
2.1 核心改造逻辑
2.1 核心改造逻辑
| 访问方式 | 租户 ID 初始来源 | 最终统一来源 | 核心操作 |
|---|---|---|---|
| IP + 参数访问 | URL 参数 tenant |
响应头 X-Tenant-Id |
提取参数 → 写入请求头 → 响应头刷新缓存 |
| 二级域名访问 | Nginx 注入的请求头 | 响应头 X-Tenant-Id |
直接读取响应头 → 刷新缓存 |
2.2.核心改造点:
- 初始化请求拦截:页面加载后,发起首个基础请求(如用户信息接口),解析响应头中的
X-Tenant-Id; - 缓存更新:用响应头返回的
X-Tenant-Id替换前端本地缓存的租户标识,保证后续请求的准确性; - 请求头透传:所有前端请求统一携带
X-Tenant-Id头,兼容两种访问方式的后端处理逻辑。
2.3.效果验证(请求 / 响应头示例):
- 请求头(Request Header):
X-Tenant-Id: oracle(Nginx 自动注入); - 响应头(Response Header):
X-Tenant-Id: oracle(Nginx 自动注入返回)。
五、改造验证
- 域名访问验证:访问
http://oracle.mf.com,检查 Nginx 日志和后端请求头,确认X-Tenant-Id为oracle; - 兼容验证:访问
http://192.168.0.14?tenant=000000,确认系统仍能正常识别租户; - 前端验证:检查前端缓存的租户 ID 是否与响应头
X-Tenant-Id一致,以响应头返回的X-Tenant-Id为准。
六、总结
本次多租户域名化改造的核心是 "租户标识的统一透传与兼容适配",关键要点如下:
- Nginx 层通过
map指令高效解析二级域名,实现租户标识的自动提取和优先级控制; - 前端兼容两种访问方式,统一从响应头获取租户 ID,保证系统无感知切换。
改造后既保留了原有 IP + 参数的访问方式,又实现了二级域名直访,显著提升了多租户系统的访问体验和可维护性。