两个客户都有一个名为“active”的字段。对一位客户,它表示顾客在过去一年购买过商品;对另一位客户,它表示服务协议仍然有效。共享连接器可以正确传送这两个字段,但如果共享规则把它们视为同一种业务状态,就可能对其中一位客户得出错误结论。这是说明性例子,并非真实部署记录。
一段关于共享平台与本地部署的讨论描述了一家公司复用大量基础设施,同时仍在每个客户环境中做不少工作。提到的比例只适用于该公司。更普遍的架构问题是:共享机制在哪里结束,本地业务含义又从哪里开始?
把传输契约与业务契约分开
传输契约可以规定:向源系统认证、读取有变化的记录、保留标识符、安全地重试并暴露故障。这些行为可以实现一次,反复测试。每个集成都需要一条可信的数据通路,因此复用很有价值。
业务契约则规定哪条记录具有权威性、某个状态代表什么、何时可以行动,以及谁能够纠正错误。
- 共享传输 身份 · 重试 · 事件 ID
交付有效事件
- 本地规则 含义 · 同意 · 时机
判断是否允许操作
- 获准操作 写入 · 审计
记录结果
业务契约取决于工作流。即使两个客户使用同样的源系统和目标系统,也可能需要不同的答案。
以商店到邮件平台的连接为例。平台可以提供事件接入、去重和审计轨迹。工作流负责人必须定义:“subscribed”是否代表针对特定营销目的的许可;购买后是否应取消购物车提醒;同意状态改变后,已经排队的消息应怎样处理。单靠字段名无法猜出这些规则,它们不是连接器可以自行决定的功能。
下方的 Tajo 示意映射直接复制三个字段。没有一行定义营销许可。复用传输方式能省工,但工作流负责人仍须明确哪种状态允许哪种操作。整齐的字段表可以暴露缺口,无法自行填补。
运行前检查同步
将客户更新同步到我的邮件平台。
客户同步
| 源字段 | 目标字段 | 规则 |
|---|---|---|
email | EMAIL | 直接映射 |
first_name | FIRSTNAME | 直接映射 |
last_name | LASTNAME | 直接映射 |
模拟数据预览通过
已映射 3 个字段 · 未写入目标系统
此示意布局参考 Tajo 的映射工具。模拟数据预览和已保存草稿都不会启用同步。
| 共享层 | 本地层 |
|---|---|
| 认证和令牌刷新 | 哪个主体可以访问这个工作流 |
| 事件传输和重试 | 哪个事件构成业务状态转换 |
| 稳定标识符和去重 | 哪些记录指向同一位真实客户 |
| 日志和恢复接口 | 谁解决有争议的状态,以及如何解决 |
| 契约验证 | 字段值的含义,以及何时可以据此行动 |
这张表说明一种设计边界,并不声称所有实现都能如此整齐地分层。
复用在掩盖分歧时失效
通用平台常会为每种例外增加一个配置字段。起初,这似乎保住了复用;久而久之,没有人能看出某个设置究竟是技术选项、法律约束,还是业务决定。共享核心变成了一个遥控器,替别人做它无权决定的事。
应该寻找稳定的不变量。“绝不把同一个源事件对同一条目标记录应用两次”可以属于共享引擎。“客户变为活跃状态时发送折扣”则不能直接共享;首先要有人定义“活跃”、允许触达的受众和优惠规则。引擎可以执行获准的规则,但不应自行发明规则。
这条边界也有利于维护。如果 API 变更,平台团队可以更新适配器及其测试。如果合格客户的定义改变,业务负责人可以更新规则和测试用例,无须等待传输层重写。边界清晰,变更才能落到有权负责的人手中。
复用机制,不要抹平含义
本地规则确实会增加一些成本。毫无可复用契约的平台,会退化为一堆定制脚本。合理的做法是先找重复的机制,再考虑抽象重复的含义。一个设计得当的共享基础能力可以接受带类型的判断条件、事件时间和操作限制,同时把该条件的业务定义留在本地。
用真实情形检验边界:取一个正常事件、一个重复事件、一个迟到的更正,以及一项已撤销的许可,逐一判断由哪一层负责响应。如果无法指派故障责任,抽象就掩盖了归属。如果新客户迫使共享的“active”枚举容纳几种互不相关的解释,共享类型就太宽泛了。
相关的部署文章讨论一项能力能否在实际工作流中运作。本文关注的是:哪些东西可以只构建一次,同时不抹掉工作流自身的含义。
层与层之间的接口应该明确到足以拒绝错误假设。共享引擎可以要求操作请求带上事件 ID、源事件时间、执行主体和声明的目的。本地工作流则提供决定是否允许操作的规则。目的缺失时,引擎应拒绝请求;规则含糊时,本地负责人必须澄清。这是保留复用能力、又不把业务决策权交给通用代码的一种实际做法。用一个获准例子和一个被拒绝例子记录契约,并在任一层变更后测试两者。
可复用的连接器应让本地业务含义更容易表达,也让执行更安全。它绝不能因为两个字段同名,就把两种不同的承诺伪装成一回事。
常见问题
集成平台通常应该复用什么?
当底层要求一致时,认证模式、传输、幂等处理、重试、日志和契约检查等稳定机制通常可以共享。
哪些内容应由具体业务定义?
字段含义、权威数据源、同意规则、时序要求,以及谁可以依据某个状态采取行动,都必须针对该业务和工作流明确确定。
团队如何检验这条边界?
尝试用现有基础能力表达新的工作流。如果这样做会改变业务含义,或把异常情况藏进通用配置,就让这段逻辑留在本地,并明确接口。