2. 事件风暴基础:领域事件、命令、聚合、限界上下文
事件风暴(Event Storming)是一种协作建模技术,由 Alberto Brandolini 提出,旨在通过高互动性的工作坊形式,快速探索复杂业务领域并建立统一语言。本章将深入剖析事件风暴画布上的四个核心构造块:领域事件、命令、聚合和限界上下文。理解这些元素是后续进行分布式事务分析与微服务拆分的基石。
2.1 领域事件(Domain Event)
领域事件是事件风暴的“第一公民”,表示业务领域中已经发生的、不可改变的事实。它通常以“过去时态”命名,例如“订单已创建”、“库存已扣减”、“支付已成功”。
- 不可变性:事件一旦发生,就不能被修改或撤销。
- 业务意义:必须对领域专家有明确的业务含义,而非技术实现细节。
- 触发后续动作:一个领域事件通常会触发一个或多个后续命令或流程。
在事件风暴工作坊中,领域事件使用橙色便签表示,并按照时间顺序从左到右排列在画布上。
| 属性 | 说明 | 示例 |
|---|---|---|
| 名称 | 过去时态的动词短语 | 订单已提交 |
| 时间戳 | 事件发生的精确时间点 | 2025-03-21 14:30:00 |
| 数据负载 | 事件携带的关键业务数据 | 订单ID、用户ID、商品列表、总金额 |
| 事件来源 | 产生该事件的聚合或外部系统 | 订单聚合 |
2.2 命令(Command)
命令是用户或外部系统发出的、希望系统执行某个操作的意图。它代表一个请求,但不保证一定会成功。命令通常以“祈使句”形式命名,例如“提交订单”、“扣减库存”、“发起支付”。
命令与领域事件之间存在明确的因果关系:一个命令的执行结果,要么产生一个领域事件(成功),要么产生一个拒绝或异常(失败)。
- 命令发起者:可以是用户(UI操作)、外部系统(API调用)、定时器(Scheduler)或另一个聚合。
- 命令验证:在命令被处理前,聚合会进行业务规则校验(如库存是否充足、用户余额是否足够)。
- 命令与事件的关系:一个命令通常对应一个或多个可能的领域事件。
在事件风暴画布上,命令使用蓝色便签表示,并放置在触发它的领域事件右侧,或与产生它的聚合相邻。
| 对比维度 | 命令(Command) | 领域事件(Domain Event) |
|---|---|---|
| 时态 | 将来时(意图) | 过去时(事实) |
| 确定性 | 可能成功或失败 | 已发生,不可变 |
| 命名方式 | 动词原形 + 宾语 | 宾语 + 动词过去分词 |
| 便签颜色 | 蓝色 | 橙色 |
| 示例 | 提交订单 | 订单已提交 |
2.3 聚合(Aggregate)
聚合是领域驱动设计(DDD)中的核心模式,它是一组相关对象的集合,作为一个整体进行数据变更的一致性边界。聚合通过聚合根(Aggregate Root)对外暴露访问入口,确保内部状态的一致性和不变性。
聚合在事件风暴画布上使用黄色便签表示,通常是一个较大的矩形区域,内部包含其管理的命令和事件。
- 聚合根:聚合中唯一可以被外部引用的实体,负责协调聚合内部对象的生命周期。
- 一致性边界:聚合内部的所有对象在同一个事务中保持一致状态。
- 标识符:每个聚合实例都有一个全局唯一的标识符(ID)。
2.4 限界上下文(Bounded Context)
限界上下文是 DDD 中用于划分系统边界的战略模式。它定义了模型、术语和业务规则的适用范围。在一个限界上下文内部,领域模型是统一且自洽的;不同限界上下文之间通过上下文映射(Context Map)进行集成。
在微服务架构中,一个限界上下文通常对应一个或多个微服务。限界上下文是微服务拆分的最重要依据。
| 限界上下文 | 核心职责 | 典型聚合 | 对外发布的领域事件 |
|---|---|---|---|
| 订单上下文 | 管理订单创建、修改、取消 | 订单聚合 | 订单已创建、订单已取消 |
| 库存上下文 | 管理商品库存的增减 | 库存聚合 | 库存已扣减、库存已释放 |
| 支付上下文 | 处理支付请求与回调 | 支付聚合 | 支付已成功、支付已失败 |
| 物流上下文 | 管理发货与配送 | 发货单聚合 | 包裹已发货、包裹已签收 |
在事件风暴画布上,限界上下文使用绿色便签或粗线框将属于同一上下文的聚合、命令和事件圈在一起,形成清晰的业务边界。
2.5 核心关系图示
下图展示了事件风暴中四个核心构造块之间的典型协作关系:用户发起命令,命令由聚合处理,聚合产生领域事件,领域事件跨越限界上下文边界触发下游上下文中的新命令。
2.6 事件风暴工作坊中的视觉约定
为了在协作建模过程中快速识别和沟通,事件风暴工作坊使用标准化的便签颜色体系。下表总结了核心元素的视觉约定:
| 构造块 | 便签颜色 | 便签形状 | 典型内容 |
|---|---|---|---|
| 领域事件 | 橙色 | 矩形 | 订单已创建 |
| 命令 | 蓝色 | 矩形 | 提交订单 |
| 聚合 | 黄色 | 大矩形 | 订单聚合(含内部实体) |
| 限界上下文 | 绿色(边框) | 虚线框 | 订单上下文 |
| 外部系统 | 粉色 | 矩形 | 支付网关 |
| 用户/角色 | 黄色(小) | 便签 | 买家 |
2.7 从事件风暴到微服务设计
事件风暴的输出可以直接映射到微服务架构设计。核心映射规则如下:
- 一个限界上下文 → 一个或多个微服务:限界上下文定义了业务边界,微服务是技术实现单元。通常一个限界上下文对应一个微服务,但当上下文内部存在高内聚低耦合的子域时,可以拆分为多个微服务。
- 一个聚合 → 一个事务边界:聚合是数据一致性的最小单元。在微服务内部,一个数据库事务只应修改一个聚合实例。
- 领域事件 → 异步消息:跨微服务的数据同步通过领域事件实现,使用消息队列(如 Kafka、RabbitMQ)保证最终一致性。
- 命令 → API 或消息:命令可以映射为 REST API 端点(同步)或消息通道(异步)。
下图展示了从事件风暴模型到微服务架构的映射关系:
2.8 本章小结
领域事件、命令、聚合和限界上下文是事件风暴建模的四大支柱。掌握它们的概念、视觉约定和相互关系,是后续章节中分析分布式事务场景、设计 Saga 编排流程、配置消息可靠投递的基础。在进入下一章之前,请确保能够回答以下问题:
- 如何区分一个业务事实是“命令”还是“领域事件”?
- 聚合在分布式事务中扮演什么角色?为什么一个事务只能修改一个聚合?
- 限界上下文如何指导微服务的拆分?
- 在事件风暴画布上,如何通过颜色快速识别不同的构造块?