4. 订单系统领域事件识别

领域事件(Domain Event)是事件风暴的核心产物,它记录了订单生命周期中发生的、对业务有意义的“已发生事实”。本章将引导你完成订单系统的领域事件识别,并最终绘制出事件风暴画布。

4.1 订单生命周期分析

一个典型的电商订单从创建到完成(或取消)会经历多个状态变迁。我们首先梳理订单的完整生命周期,这是识别领域事件的基础。

核心原则: 领域事件使用“过去时态”命名(如 OrderPlaced),表示一个已经完成且不可变的事实。每个事件都应触发后续的业务流程或状态变更。

订单生命周期通常包含以下主要阶段:

  1. 创建阶段: 用户提交购物车内容,系统生成订单。
  2. 支付阶段: 用户完成支付,系统确认收款。
  3. 履约阶段: 仓库备货、发货,物流开始配送。
  4. 完成/关闭阶段: 用户确认收货或订单因超时/取消而关闭。

下表展示了订单状态与对应领域事件的映射关系:

订单状态 触发动作 领域事件 事件含义
待支付 用户点击“提交订单” OrderPlaced 订单已创建,等待用户支付
已支付 支付网关回调成功 OrderPaid 订单已支付,等待仓库处理
备货中 仓库系统接单 OrderPreparing 仓库开始拣货、打包
已发货 快递员揽收扫描 OrderShipped 包裹已出库,物流开始运输
已签收 用户确认收货或系统自动确认 OrderDelivered 订单已完成,交易闭环
已取消 用户取消或系统超时取消 OrderCancelled 订单终止,可能触发退款流程

4.2 识别关键领域事件

在事件风暴工作坊中,我们使用橙色便利贴来记录领域事件。以下是订单系统中必须识别的关键事件,它们构成了分布式事务的边界和触发点。

实战提示: 在 Go 微服务架构中,每个领域事件通常对应一个 protobuf 消息定义,并通过消息队列(如 Kafka、RabbitMQ)进行跨服务发布与订阅。

4.2.1 核心业务事件

  • OrderPlaced(订单已创建):用户提交订单后触发。包含订单号、商品列表、总金额、收货地址等信息。这是整个订单流程的起点。
  • OrderPaid(订单已支付):支付服务确认收款后触发。包含支付流水号、支付方式、支付时间。该事件会通知库存服务扣减库存,通知物流服务准备发货。
  • OrderShipped(订单已发货):仓库完成发货操作后触发。包含物流单号、快递公司、发货时间。该事件会通知用户服务发送物流通知。
  • OrderDelivered(订单已签收):用户确认收货或系统自动签收后触发。该事件会触发积分服务增加用户积分,并完成订单的财务结算。
  • OrderCancelled(订单已取消):用户主动取消或系统因超时/风控取消订单时触发。该事件会触发退款流程,并通知库存服务恢复已扣减的库存。

4.2.2 补偿与异常事件

在分布式系统中,事务失败是常态。以下事件用于处理异常场景,保证最终一致性:

  • PaymentFailed(支付失败):用户支付时余额不足或支付网关返回失败。系统应保留订单状态,允许用户重试支付。
  • InventoryShortage(库存不足):支付成功后,库存服务发现实际库存不足。此时需要触发订单取消和退款流程。
  • DeliveryFailed(配送失败):物流公司反馈无法配送(如地址错误、拒收)。系统需要通知用户并协商后续处理。

4.3 事件风暴画布绘制

事件风暴画布将领域事件按时间顺序从左到右排列,形成一条“事件流”。我们使用 SVG 绘制订单系统的核心事件风暴画布。

订单系统事件风暴画布 订单系统事件风暴画布(核心流程) OrderPlaced OrderPaid OrderShipped OrderDelivered Cancelled 画布说明: • 蓝色节点(OrderPlaced):订单创建,触发库存预占和支付等待。 • 绿色节点(OrderPaid):支付成功,触发库存扣减和物流准备。 • 红色节点(Cancelled):异常终止,触发库存恢复和退款流程。

上图展示了订单系统的核心事件流。在实际的事件风暴工作坊中,我们还会在事件之间添加命令(Command)和聚合(Aggregate),形成完整的画布。以下是包含命令和聚合的扩展画布:

订单系统完整事件风暴画布(含命令与聚合) 完整事件风暴画布(命令 + 聚合 + 事件) 命令 PlaceOrder PayOrder ShipOrder ConfirmDelivery 聚合 Order Aggregate Payment Aggregate Inventory Aggregate Logistics Aggregate 事件 OrderPlaced OrderPaid OrderShipped OrderDelivered 画布结构说明: • 命令(蓝色):用户或外部系统发起的操作请求,如 PlaceOrder、PayOrder。 • 聚合(黄色):负责处理命令并产生事件的业务对象,如 Order Aggregate。 • 事件(红色):聚合状态变更后发布的不可变事实,驱动后续流程。

4.4 事件风暴画布在 Go 微服务中的映射

事件风暴画布不仅是一种设计工具,它可以直接映射到 Go 微服务的代码结构:

事件风暴元素 Go 微服务实现 示例代码
领域事件 protobuf 消息定义 + 事件结构体
type OrderPlacedEvent struct {
    OrderID   string
    UserID    string
    TotalAmount float64
    Items     []OrderItem
    PlacedAt  time.Time
}
命令 gRPC 服务接口或 HTTP Handler
func (s *OrderService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) {
    // 验证命令
    // 调用聚合方法
    // 发布事件
}
聚合 领域模型 + 状态机
type OrderAggregate struct {
    ID     string
    Status OrderStatus
    Items  []OrderItem
    // 事件存储
    Events []interface{}
}

func (a *OrderAggregate) PlaceOrder(cmd PlaceOrderCommand) error {
    // 业务逻辑校验
    a.Status = OrderStatusPending
    a.Events = append(a.Events, OrderPlacedEvent{...})
    return nil
}
事件流 消息队列(Kafka / RabbitMQ)
// 发布事件到消息队列
func (s *OrderService) publishEvent(event interface{}) {
    data, _ := json.Marshal(event)
    s.producer.Publish("order-events", data)
}
分布式事务注意事项: 在事件驱动的架构中,跨服务的事务一致性需要通过 Saga 模式或 Outbox 模式来保证。例如,OrderPlaced 事件发布后,如果库存服务扣减失败,需要发布 OrderCancelled 事件来补偿。这部分内容将在后续章节详细展开。

4.5 本章小结

  • 领域事件是订单系统中不可变的事实记录,使用过去时态命名。
  • 订单生命周期包含创建、支付、履约、完成/关闭四个阶段,对应 6 个核心领域事件。
  • 事件风暴画布将命令、聚合、事件按时间顺序排列,形成完整的业务流视图。
  • 在 Go 微服务中,事件风暴元素可以直接映射为 protobuf 消息、gRPC 接口、领域模型和消息队列。