Customer-Publisher(客户-供应商关系)
解决什么问题:多个 BC 之间有明确上下游,但上游有多个下游客户——单纯的 Customer-Supplier 表达不了"多客户共享同一发布物"——Customer-Publisher(有时称 OHS / PL 组合)让上游把"稳定的服务接口"作为产品发布,下游作为客户消费。
它是什么
Customer-Publisher 是 Vernon 在 Ch 3 提出的 BC 关系之一(Open Host Service + Published Language 的组合)——上游 BC 把稳定接口 / 标准数据格式作为"发布物",多个下游 BC 作为"客户"消费:
- Publisher(发布方):上游 BC,提供稳定 API + 标准数据格式
- Customer(客户方):下游 BC,订阅 Publisher 的发布物
- 核心承诺:Publisher 必须长期兼容,不能随便破坏客户
- 核心权利:Customer 不需要 ACL(因为 Publisher 已经做了翻译)
Vernon Ch 3: "An Open Host Service defines a formal protocol that gives access to your BOUNDED CONTEXT as a set of services." "Published Language is a well-known shared language that both teams use."
V2 视角(B6 权衡):Customer-Publisher = 上游主动承担兼容成本,换取下游零成本集成——显式权衡"灵活性 vs 易用性"。
关键属性
| 属性 | Publisher(上游) | Customer(下游) |
|---|---|---|
| 角色 | 服务的提供方 | 服务的消费方 |
| 权力 | 强(定义接口) | 弱(接受接口) |
| 义务 | 长期兼容 + 版本管理 | 按约定消费 |
| 优势 | 一次发布,多客户复用 | 零翻译成本(OHS + PL 保证) |
| 风险 | 兼容债积累 | 受上游节奏约束 |
| 反模式 | 上游随意破坏接口 | 下游反推上游改接口 |
| 核心约束 | 必须提供 Open Host Service 或 Published Language | 必须接受上游约束 |
怎么用
场景 1:识别 Customer-Publisher 候选
识别标准:
- 一个 BC 被 3+ 个下游 BC 依赖(多客户)
- 集成模式重复(每个下游都做同样翻译)
- 上游 BC 有能力维持稳定接口(有 SLA 团队)
处理:
- 把上游接口抽象为 Open Host Service(OHS)——REST API / gRPC / 事件流
- 把数据格式标准化为 Published Language(PL)——JSON Schema / Avro / Protobuf
- 文档化:OHS 接口文档 + PL 数据字典
- 版本管理:v1 / v2 / deprecation 周期
场景 2:OHS + PL 设计(Open Host Service)
# Publisher 提供 REST API(OHS)
POST /api/v1/orders # 创建订单
GET /api/v1/orders/{id} # 查询订单
# Publisher 提供标准事件格式(PL)
{
"event_type": "OrderCreated",
"version": "1.0",
"occurred_at": "2026-06-23T10:00:00Z",
"payload": {
"order_id": "ord_123",
"customer_id": "cus_456",
"items": [...]
}
}
# Customer 直接消费(无需 ACL)
class OrderHandler:
def on_event(self, event):
# 直接用标准格式
order_id = event["payload"]["order_id"]
...场景 3:版本管理策略
问题:Publisher 改了接口,下游会破坏。
处理:
- SemVer 严格遵守:MAJOR = 破坏性改动,MINOR = 加功能,PATCH = 修复
- 同时支持多版本:v1 / v2 并行运行 ≥ 6 个月(deprecation period)
- deprecation 通知:提前 3-6 个月通知所有客户
- 迁移窗口:客户提供迁移指南 + 工具
SE@G Ch 15 Deprecation 配套原则——deprecation 必须有显式生命周期。
场景 4:从 Customer-Supplier 演化
起点:上游 BC 只有 1-2 个下游,Customer-Supplier 关系足够。
演化:
- 下游增加到 5+——重复集成成本出现
- 重构为 Customer-Publisher——上游提供 OHS + PL
- 下游不再需要 ACL——降低集成成本
反之:如果下游减少到 1 个,Publisher 价值降低,回到 Customer-Supplier。
常见误区
- "所有 BC 都应该是 Customer-Publisher"——错。只有多客户的上游才适合。单下游的 BC 用 Customer-Supplier 就够,强做 OHS = 过度工程
- "OHS = REST API"——错。OHS 是长期承诺的接口,不是"提供 HTTP 就行"。承诺包括版本管理、deprecation、稳定性
- "PL = JSON Schema"——错。PL 是跨团队共识的数据字典——必须有业务语义,不只是技术 schema。
"order_id"是技术,PL 应该明确这是"订单唯一标识,业务全局 ID" - "Publisher 可以随意改"——错。Publisher 的最大成本是兼容债——一旦承诺 OHS,长期被约束。改前必须评估下游影响
- "下游不需要 ACL"——错。OHS + PL 保证数据格式稳定,但业务语义变化下游仍需要适配。语义变化 = Publisher 发新版本
- "Customer-Publisher = Customer-Supplier + ACL"——错。Customer-Publisher 是上游主动兼容(OHS),ACL 是下游主动翻译(Customer-Supplier + ACL)。方向相反
关键洞察
Customer-Publisher = 上游承担兼容成本换下游零翻译成本——是"标准化 vs 灵活性"的显式权衡。
何时选 Publisher:
- 多客户(≥ 3 下游)→ 标准化收益大于灵活性损失
- 上游有 SLA 团队 → 能承担兼容义务
- 下游同质性高 → 客户需求相似
何时不选 Publisher:
- 单一下游 → 强做 OHS 浪费
- 上游快速演化 → 兼容债爆炸
- 下游需求差异大 → 标准化反而损失灵活性
这是 V2.7 B6 权衡的工程化——标准化收益 > 灵活性损失时选 Publisher,反之选 Customer-Supplier。
相关链接
- 9 种 BC 关系——Customer-Publisher 是其中之一
- Context Map——关系落地的图
- Event Contract——Published Language 的具体实现
- Interface Contract——OHS 的具体实现
- [V3 涌现作为] · 权衡——标准化的代价
- 源典 IDDD Ch 3——Vernon 原书精读
- 源典 EDM Ch 3——事件契约设计