proposal.md 3.3 KB

状态(2026-04-18 立项):提案阶段,未实施 优先级:高。与 add-mjava-com 并行,共同承担"多用户/多客户使用支持"大方向。

Why

现有 mjava-mcli / mjava-shunfeng / mjava-guangming 三个客户子项目采用"一客户一 jar"模式,每次加新客户都要:

  1. 复制 mcli 模板 → 改 artifactId / port / context-path
  2. application-{profile}.yml 硬编码该客户的 appKey/appSecret/corpId
  3. 单独部署一个 JVM 实例

这种方式在客户数量少(≤ 5)时尚可,但问题:

  • 新客户上线 = 发布新版本 + 运维新增部署节点,交付周期慢
  • 一客户一实例,资源利用率低
  • appKey/appSecret 静态写在 yml,切换客户需要重启 + 重新发包
  • 实例间没有共享缓存,每客户独立维护自己的 token 生命周期

需要一个支持"一个 jar 同时服务多个客户"的子项目模板 mjava-pro,按请求上下文动态加载客户配置、token 按租户隔离缓存,加客户 = 新增一条宜搭应用表记录,无需改代码和重启。

What Changes

新增子模块 mjava-pro/,具备以下能力:

  • 租户解析:请求入口识别 X-Tenant-Id header(或 subdomain / path prefix,实现时选定),未识别到返回 401
  • 应用配置动态加载:从宜搭"应用表"(formUuid 配置在 application.yml)按 tenantId 查询 appKey / appSecret / corpId / 其他授权参数;命中后缓存到内存(TTL 可配,默认 10 分钟)
  • Token 隔离UtilToken key 扩展为 {tenant}:{vendor}:{appKey},各租户独立缓存不互相覆盖
  • Client 透传:基座 DDClient / YDClient 等保持原签名不变;mjava-pro 内部通过 TenantContext(ThreadLocal)传 appKey/appSecret 进去
  • 配置表结构约定:宜搭应用表字段规范固定在 spec.md 中(tenantId / vendor / appKey / appSecret / extraJson / enabled / ...)

Capabilities

New Capabilities

  • multi-tenant-runtime:单部署多租户运行时,按请求上下文路由到对应客户配置
  • tenant-registry:从宜搭应用表加载租户配置的注册中心抽象

Modified Capabilities

Impact

  • 新增模块mjava-pro/(独立 jar,默认端口 9010,context-path /api/pro
  • 新增代码(预计):
    • TenantContext.java + TenantInterceptor.java(ThreadLocal 管理)
    • TenantRegistryService.java(查宜搭应用表)
    • DynamicDDClientProxy.java(包装基座 DDClient,按 tenant 注入凭据)
    • application.yml + application-{dev,prod}.yml.example
  • 基座影响:可能需要 UtilToken 支持 key 命名空间;评估后若需要再开子提案
  • 现有客户模块:零影响,mcli/shunfeng/guangming 继续运行
  • 部署:单 pro jar 可接管 N 个客户,运维新增客户只在宜搭应用表加一行记录即可

Non-Goals

  • ❌ 不替代现有 mjava-mcli/shunfeng/guangming(已交付客户保持原架构)
  • ❌ 不引入 Redis(tenant 配置缓存仍走 TimedCache,单实例足够;若将来多实例再评估)
  • ❌ 不做跨租户数据聚合 / 租户级计费 / 多租户数据库分离
  • ❌ 本提案不涵盖前端租户切换 UI(前端按现有方式各自管理)