2. 多租户模型:数据隔离模式、租户上下文传递与路由策略

多租户(Multi-Tenancy)是 SaaS 架构的核心。在 CI/CD 流水线中,鉴权与拦截链路必须准确识别当前请求属于哪个租户,并根据租户的隔离级别选择正确的数据源与资源路径。本章从数据隔离模式、上下文传递机制和路由策略三个维度展开,为后续的拦截与回滚设计奠定基础。

2.1 数据隔离模式:共享 vs. 独享

数据隔离决定了租户之间数据可见性与安全边界。主流模式有三种,下表从隔离粒度、运维成本和流水线适配三个角度进行对比:

隔离模式 数据库实例 Schema / 表 隔离强度 运维成本 CI/CD 适配要点
独享数据库 每个租户独立实例 独立 Schema 最高 高(备份/扩容/迁移按租户) 流水线需动态生成连接串;回滚按租户粒度执行
共享数据库·独享 Schema 共享实例 每个租户独立 Schema 中 中(Schema 管理复杂) 流水线需在 SQL 迁移中注入 tenant_id 或 schema 前缀
共享数据库·共享表 共享实例 共享表 + tenant_id 列 最低 低(索引/分区需优化) 流水线需确保所有 DML/DDL 包含租户过滤条件
实践建议:在 CI/CD 鉴权拦截链路中,建议将租户隔离模式作为元数据存储在配置中心。流水线在部署阶段根据租户元数据动态选择数据源,避免硬编码。

2.2 租户上下文传递

租户上下文(Tenant Context)是贯穿整个请求生命周期的租户标识与隔离属性集合。在微服务架构中,上下文传递必须做到无侵入、可追溯。

2.2.1 上下文数据结构

// TenantContext 核心字段
{
  "tenantId": "t-abc123",          // 租户唯一标识
  "tenantCode": "acme-corp",       // 租户业务编码
  "isolationLevel": "SCHEMA",      // 隔离模式: DATABASE | SCHEMA | TABLE
  "region": "us-east-1",           // 地域标识,用于多区域路由
  "features": ["audit", "rbac"],   // 租户特性标记
  "requestId": "req-456def"        // 请求链路追踪 ID
}

2.2.2 传递方式对比

传递方式 实现机制 优点 缺点 适用场景
HTTP Header X-Tenant-Id / X-Tenant-Code 简单、网关可解析 需手动透传,易丢失 API 网关、边缘代理
JWT Claims Token 内嵌 tenant 字段 自包含、防篡改 Token 体积增大 OAuth2 / OpenID Connect
gRPC Metadata gRPC 上下文附加键值对 框架原生支持 仅限 gRPC 协议 内部服务间调用
ThreadLocal / AsyncLocal 语言级上下文容器 代码侵入小 异步场景需显式传播 单体或服务内逻辑
避坑提醒:在 CI/CD 流水线中,如果使用 ThreadLocal 传递租户上下文,务必在异步任务(如消息队列、定时任务)中手动复制上下文,否则会导致租户信息丢失,引发数据泄露或鉴权失败。

2.3 租户路由策略

租户路由(Tenant Routing)决定请求到达后如何根据租户上下文选择数据源、服务实例或配置版本。在鉴权拦截链路中,路由发生在身份认证之后、业务逻辑之前。

2.3.1 路由层级

  1. DNS 路由: 根据租户子域名(tenant1.app.com)解析到不同集群或入口。
  2. API 网关路由: 根据 Header 或 Path 前缀(/api/tenant/{id}/)分发到后端服务。
  3. 数据访问层路由: 根据租户隔离模式选择数据库连接池或 Schema。
  4. 缓存路由: 为每个租户使用独立的 Redis 命名空间或 Key 前缀。

2.3.2 路由策略决策树

下图展示了在鉴权拦截链路中,系统如何根据租户元数据逐层决策路由目标:

租户路由决策流程(鉴权拦截链路) 请求到达 身份认证(JWT/OAuth) 提取租户上下文(Header/Token) 隔离模式 判断 独享数据库 共享 DB · 独享 Schema 共享表 执行鉴权拦截 + 数据路由 路由决策在认证后、业务前执行 确保租户边界不泄露

2.4 流水线中的租户路由配置

在 CI/CD 流水线中,租户路由策略需要作为可配置的元数据注入到部署产物中。推荐使用配置中心(如 Consul、etcd、Nacos)存储以下路由表:

# 租户路由配置示例 (YAML)
tenants:
  - id: "t-001"
    code: "acme"
    isolation: "SCHEMA"
    datasource:
      host: "db-shared-01.internal"
      port: 5432
      database: "saas_prod"
      schema: "acme_schema"
    cache:
      prefix: "acme:"
    region: "us-east-1"

  - id: "t-002"
    code: "globex"
    isolation: "DATABASE"
    datasource:
      host: "db-globex.internal"
      port: 5432
      database: "globex_db"
      schema: "public"
    cache:
      prefix: "globex:"
    region: "eu-west-1"
流水线集成点:在部署阶段,流水线从配置中心拉取租户路由表,生成每个租户的数据库连接池、缓存命名空间和 API 路由规则。回滚时,只需将路由表指向上一版本的数据库快照或 Schema 备份,即可实现租户级快速回退。

2.5 本章小结

  • 数据隔离模式决定了租户数据的物理边界,直接影响流水线中数据源的选择与回滚粒度。
  • 租户上下文传递必须覆盖 HTTP、gRPC、异步消息等所有通信协议,避免上下文丢失导致的安全漏洞。
  • 租户路由策略在鉴权拦截链路中起到承上启下的作用:认证后提取租户标识,业务前完成数据源与配置的绑定。
  • 在 CI/CD 流水线中,将租户路由表作为一等配置资产管理,是实现自动化部署与精细化回滚的前提。