design.md 6.9 KB

Design

关键决策

1. 为什么是三档而不是两档或四档

两档(公共/独立)的问题:把「中等复杂度独立部署」一刀切要么进公共池(污染共享 jar),要么直接独立仓(运维成本高、与基座脱节)。中等客户无处安放。

四档(极轻/轻/中/重)的问题:极轻和轻的边界在实操里区分意义小,都是「不写 Controller,只配凭据」。增加判定成本不增加决策价值。

三档(A/B/C)的依据:以「是否需要新写 Java 代码」(A→B 分界)和「是否在我们机房部署」(B→C 分界)作两个硬切点。两个切点正交、可观测、不依赖主观判断。

2. 各档物理落点约定

物理位置 artifactId / git 仓 部署形态
A mjava-pro/ 共享 jar mjava-pro(仓内) 一个 jar 跑 N 客户,端口 9010
B mjava-ai/mjava-{客户}/ mjava-{客户}(仓内,独立子模块) 一客户一 jar,端口由客户分配
C 独立 git 仓(不在 mjava-ai) mjava-{客户}(独立仓 root artifact) 客户自管部署

B 档命名:直接用客户拼音/英文短名,如 mjava-akds / mjava-sikuwh。禁带客户中文全名或冗长缩写。

C 档参照:现有 cur/mjava-guangming/(4 模块仓) + akds(独立仓)。命名沿用历史习惯,本 change 不追溯改名。

3. A→B→C 升级路径的硬指标

判定矩阵以「触发即升档」为准则,触发条件必须可观测(不靠主观判断「这个客户复杂」):

升档 触发条件(任一即触发)
A → B (1) 客户需要写自定义 Controller / Service / Entity;(2) 客户需要私有数据库 schema;(3) 客户需要独立部署节点(隔离故障域)
B → C (1) 客户提供自己的部署环境(私网/客户机房/客户 K8s);(2) 客户要求源代码进客户 git;(3) 客户要求 mjava 基座做大幅分叉(≥3 个文件改基座)

反向降档:不支持。一旦升档,物理资产已经独立,回退成本远高于继续维护。

4. mjava-pro 入驻 SOP(A 档具体步骤)

新客户走 A 档时操作步骤:

  1. 校验触发条件:确认客户不命中 A→B 任一硬指标
  2. 宜搭应用表加一行:tenantId / vendor / appKey / appSecret / extraJson / enabled
  3. 凭据热验证:调 mjava-pro/api/pro/_diag/tenant/{tenantId} 探活(接口归 add-mjava-pro 实现)
  4. 上线通告:邮件抄送(运维 + 客户对接人),记录 tenantId 进 README 客户清单段

必填字段(spec R3 正式定义):tenantId(业务唯一)/ vendor(dingtalk|aliwork|...)/ appKey / appSecret / corpId(钉钉系才需)/ enabled。其余按 vendor 走 extraJson。

隔离边界

  • DB:A 档客户共享 mjava-pro 的 DB schema(用 tenantId 字段隔离行级数据)
  • 缓存:UtilToken key 命名空间扩为 {tenant}:{vendor}:{appKey}(add-mjava-pro 已约定)
  • 日志:traceId 自动带 tenantId 维度(MDC 追加)

5. mjava-com 对外暴露白名单规则

mjava-com 暴露的是「mjava 基座的 Client/Service 能力」,但不是所有方法都自动开放,按以下规则:

  • 白名单制:在 application.yml 显式列出可暴露的 {vendor}.{action}(如 dingtalk.user.getaliwork.form.save),未列入即 404
  • 危险动作禁开:删除类(delete)、批量改类(batch update)、租户管理类(tenant.create)默认禁开,需主仓维护者 ACK 才能加
  • 限流默认值:每调用方 60 QPS(本地 RateLimiter,进程级),可在 application.yml 按调用方覆盖
  • 审计强制:每次调用打全字段审计日志(调用方 / vendor / action / 入参摘要 / 出参摘要 / 耗时 / 成功标志),不可关闭

审批流程:新增白名单条目走 PR + 主仓维护者 review,commit message 标 feat(com): 开放 {vendor}.{action} 暴露

6. C 档客户独立仓与 mjava-ai 的关系

C 档客户仓不依赖 mjava-ai 发布的 jar,而是 fork 基座源码到自己仓内(如 mjava-guangming/mjava/)。原因:

  • 客户私网 / 客户机房环境通常无法访问我们的 maven 私服
  • 客户要求源码进客户 git,jar 依赖模型不可行
  • 客户的基座分叉常需要快速改(如临时加字段、兼容客户老接口),等上游回流太慢

版本号约定:C 档客户仓内 mjava 基座 pom 的 version保持与上游同步的语义版本(如 mjava-ai 的 mjava 是 0.0.3,则客户仓的 mjava 也是 0.0.3,分叉改动通过 git 历史追溯,改版本号)。这样未来客户问「我用的是哪版上游」时,git diff 直接可比。

回流通道(可选):客户仓如有通用价值的改动(修 bug、加产品方接口),鼓励上游 cherry-pick 回 mjava-ai。具体流程不强制,按工程师习惯。

R4 跨仓 grep 范围:C 档客户仓内的代码纳入 mjava-ai 的 R4 grep(已在 standardize-client-service-layering 的 design 里约定「基础建设期默认仅本仓」),与本 change 一致。

7. README / CLAUDE.md 改写策略

README 「子项目速览」表加「档位」列,但不在 README 直接展开判定矩阵(避免重复)。改为:

| 子模块 | 端口 | Context | 档位 | 状态 |
|--------|------|---------|------|------|
| `mjava-mcli` | 9001 | /api/mcli | B 模板 | 新客户模板 |
| `mjava-pro` | 9010 | /api/pro | A 容器 | 多租户单部署骨架 |
| `mjava-com` | 9020 | /api/com | — | BaaS 网关骨架 |

「新客户接入」段改为指向 openspec/specs/customer-tiering/spec.md(archive 后位置),三档分流由 spec 权威。

CLAUDE.md 加一行:「新客户接入:先查 customer-tiering 决策树选档 → 按档执行 SOP」。

拒绝的方案

  • 只写文档不入 spec — 拒绝。客户接入决策是高频判断点,必须走 capability spec 才能被 R4 类规则交叉引用
  • 强制所有客户必先入 A 档观察 1 个月再决定升 B/C — 拒绝。增加客户接入摩擦,且部分客户初次接入就明显是 C 档(如客户机房),强观察期是无效流程
  • B 档不在 mjava-ai 仓内,单独建 mjava-customers 仓 — 拒绝。B 档客户少时拆仓成本高于聚合;mjava-ai 仓内子模块隔离已足够,pom 聚合也能并行编译
  • A→B 触发条件包含「客户数据量」(如 > 1M 行) — 拒绝。数据量是结果不是原因;真正的原因是「需要私有 schema」,已在 A→B (2) 覆盖
  • C 档客户仓强制每月同步上游 mjava — 拒绝。客户仓独立维护权属客户工程师,强同步反而干扰客户工程师节奏
  • 将「客户复杂度」作为判定因子 — 拒绝。「复杂」不可观测,会变成主观打分;改用「需要写 Java 代码」「需要客户机房」两个硬切点