分布式系统中的解耦模式:概要事件 - mathiasverraes


不要发出领域事件流,而是发出一个概要/摘要事件Summary Event。

问题
业务流程涉及许多步骤,每个步骤都会产生领域事件。事件的消费者依赖于这些事件中的信息,并要侦听所有这些事件以做出有意义的决定。当只有少数事件类型时工作很好,但是当事件类型的数量很多时,我们可以发现消费者需要对生产者业务流程进行了解,消费者现在几乎就像一个微观管理者,看着生产者的一举一动,并立即报告生产者所做的一切。
这存在风险:当原始业务流程演变发展时,可能会添加,删除或更改事件类型。就需要对消费者进行更改以适应新的事件类型,并且要么同时部署,要么具有良好的版本控制策略。
如果有多个消费者,所有人都需要了解生产者发出的每种类型的事件,情况会变得更糟。通常也会有一些重复:每个消费者都会根据事件投射相似或相同的状态。

解决
原始业务流程可以将所有事件私下保留,而不是发出每个事件。在流程结束时,该流程会发出一个概要事件。此事件是冗余的,因为它包含前面事件中已有的信息。消费者现在只是收听这个概要事件,而不是了解发出的每一个事件,这个事件告诉他们需要知道的一切,几乎没有与他们无关的信息。消费者不需要在流程中跟踪状态变化,因为他们最终得到了所有变化,然后可以对它们采取行动。

通过检查消费者,可以发现使用概要事件模式的机会:如果消费者监听多种事件类型,但只有一种事件类型导致消费者做一些有意义的领域操作(除了保留状态),这是一个好兆头。生产者也提供线索:业务流程涉及创建某种人工制品,商业价值不一定在人工制品本身,而是在人工制品创建之后的使用。(Cyrille的@TODO Cfr Three Archetypes)

案例
许多业务流程涉及为以后的生产用途创建一个人工制品:在一个订购流程中,不同的用户可能会添加和删除他们希望订购的项目的一行行条目,他们可能会改变他们想要的物品数量。客户经理可能会根据可用库存更改数量更改价格等等。
在最初的设计中,消费者监听:LineItemWasAdded,LineItemWasRemoved,QuantityWasChanged,PriceWasChanged,以及ShippingAddressWasAdded等事件;消费者(比如OrderFulfilment流程)会监听大多数这些事件,并预测需要打包和发运的项目列表。

但流程处理OrderFulfilmentProcess在事件OrderWasPlaced到来之前什么都不做,直到收到这个事件,表示是它开始行动的时候了。在OrderWasPlaced事件没有冗余信息,所以它主要是有OrderId,别的都不需要。

我们现在可以重构这个订购流程,以保持其所有事件的私密性。我们制作一个公共事件OrderWasPlaced,但是这个事件包含有关订单的完整信息。实际上,OrderWasPlaced是实际订单的文档。(@TODO我相信这是企业集成模式中的文档消息模式)。

在订单下游部门工作的人通常不了解订单作为草案指定中发生的细节变更,他们只接受包含结果订单的消息,然后采取行动。

弱点:

  1. 有时,消费者确实需要了解生产者的许多内部细节才能完成其工作。在这种情况下,概要事件模式没有用,因为它不仅包含结果信息,还包含有关流程中每个步骤的元数据。
  2. 在上面的订购示例中,OrderFulfilment不关心订单的价格。比方说RevenueReporting,另一个消费者关心的是价格而不是订购的确切商品。然而,他们都收到了同样的OrderWasPlaced事件。可能存在一个问题例如,其中某些信息是敏感的,只应该暴露给一方。另外一方隐瞒。
  3. 新增了另一种事件类型Summary Event,即“替换所有标准的新标准”。
  4. 这Summary Event可能不属于生产者的领域。在这种情况下,我们可以添加一个中间服务,它消耗生产者的事件,汇总它们,然后发出Summary Event消费者。