两条定制通道
xly 客户通过两条不同路径定制系统。理解区别很关键:它们能力不同、成本不同、运维后果也不同。
通道 1 — 通过后台编辑元数据
这是受支持、由 PM 驱动的路径。客户实施人员(或客户自己)打开后台构建器,进入某个模块,然后在元数据表中插入 / 更新 / 删除行:
-
gdsmodule:注册新模块。 -
gdsconfigformmaster+gdsconfigformslave:定义表单。 -
gdsconfigformcustomslave:添加每租户字段覆盖(切片 4)。 -
gdsconfigformpersonalize:按租户覆盖表单 SQL / where / order。 -
gdsjurisdiction:授予或限制权限。 -
gdsroute、gdsformconst、sysbillnosettings等:按需配置。
这些修改是数据。它们跟随客户数据库。它们在后台界面中可见,PM 可以审计。框架运行时在每次请求中读取它们(带缓存)。Java 代码不变;应用行为由这些行决定。
这是架构希望客户优先使用的路径。至于真实比例是不是 90/10 偏向通道 1,代码库里没有统计;经验信号是 script/客户/ 下已经有 18 个客户目录,说明有相当一部分客户需要通道 1 表达不了的东西。因此,“90% 以上应该在这里”更像目标,而不是实测事实。
通道 2 — 每客户 SQL 覆盖
这是逃生口。当元数据无法表达客户需求时使用,通常是因为客户需要不同的过程逻辑,而不仅是不同字段或标签。工程师会把手写 SQL 文件提交到代码库中的 script/客户/<customer>/<file>.sql。文件通常包含一对 DROP PROCEDURE ... CREATE PROCEDURE,视图替换则是 DROP VIEW ... CREATE VIEW。
然后 DBA 或工程师把该文件手工应用到目标客户的 MySQL schema。从那一刻起,该客户数据库中就有一个与标准同名但主体不同的存储过程。
细节见切片 5。
这个通道真实存在且用于生产:当前代码库中有 18 个客户覆盖目录。它也比通道 1 显著更贵。
如何选择
使用通道 1的情况:
- 定制是结构性的(新字段、新模块、不同标签)。
- 行为可通过修改 SQL 片段表达(
sSqlStr/sWhere/sOrder)。 - 定制应在后台中可见,并可由 PM 编辑。
- 希望它跟随数据库备份。
使用通道 2的情况:
- 客户需要框架 Add/Update/Calc 过程无法表达的过程逻辑。
- 需要替换存储过程主体,而不是只在周围注入 SQL 片段。
- 运行时差异应放在源码控制的
.sql文件中(script/客户/<customer>/下),这样维护人员审查客户运行时时能一眼看到每客户变更,而不是只有连接到实时 DB 后才能发现。
通道 2 几乎总是最后手段。只有确认通道 1 做不到时才使用。
成本对比
| 属性 | 通道 1(元数据) | 通道 2(SQL 覆盖) |
|---|---|---|
| 跟随 DB 备份 | 是 | 只有目标客户 schema 被备份时才是 |
| 后台中可见 | 是 | 否 |
| PM 可编辑 | 是 | 否,仅工程师 |
| 跨租户影响 | 无,行按 sBrandsId 作用域隔离 |
无,按客户 schema 应用 |
| schema 重建后自动恢复 | 是,行在 DB 中 | 否,必须手工重新执行 |
| 单一来源可审计 | 是,DB 行 + sMakePerson
|
部分,文件在 repo 中,但应用步骤没有日志 |
| 读代码库能否发现 | 需要连接 DB | 是,文件位于 script/客户/
|
对切片读者意味着什么
当某个切片描述“标准行为”时,指的是定制完全位于通道 1 中的租户所看到的行为。带有通道 2 覆盖的客户,在被替换的存储过程上可能会看到不同运行时行为;框架控制器代码无法分辨差异。分析这类客户的运行时行为必须查看已部署 schema,而不能只看代码库。