我是 EDA 的新手,我已经阅读了很多关于好处的内容,并且可能有兴趣在我的下一个项目中应用它,但仍然没有理解一些东西。
引发事件时,哪种模式最适合:
- 将事件命名为“CustomerUpdate”并包含有关客户的所有信息(更新与否)
- 将事件命名为“CustomerUpdate”并仅包含真正已更新的信息
- 将事件命名为“CustomerUpdate”并包含最少信息(标识符)和/或 URI,以让消费者检索有关此客户的信息。
我问这个问题是因为我们的一些活动可能是沉重而频繁的。
感谢您的回答和时间。
我是 EDA 的新手,我已经阅读了很多关于好处的内容,并且可能有兴趣在我的下一个项目中应用它,但仍然没有理解一些东西。
引发事件时,哪种模式最适合:
我问这个问题是因为我们的一些活动可能是沉重而频繁的。
感谢您的回答和时间。
将事件命名为“CustomerUpdate”
首先让我们从您的活动名称开始。事件的目的是描述已经发生的事情。这与命令不同,命令是为尚未发生的事情发出指令。
您的事件名称“CustomerUpdate”在这方面听起来模棱两可,因为它可能描述过去的某事或未来的某事。
CustomerUpdated会更好,但即便如此,Updated也是另一个模棱两可的术语,并且在业务环境中是非特定的。为什么在这种情况下更新了客户?是因为他们更改了付款细节吗?搬家了?他们是从白银升级到黄金的吗?事件可以根据需要进行具体化。
乍一看,这似乎是多虑了,但是当您从事件有效负载中删除数据和上下文时,事件命名变得特别相关,更多地转向瘦事件(您的问题中的“选项 3”,我将在下面讨论)。
这并不是说在这种粒度级别定义事件总是合适的,只是它是在项目早期向您开放的一条途径,它可能会在以后支付红利(或者可能会让您淹没成千上万的事件类型)。
回到您的实际问题,让我们依次选择您的每个选项:
将事件命名为“CustomerUpdate”并包含有关客户的所有信息(更新与否)
我们将这种“模式”称为Fat消息。
胖消息(也称为快照)表示所描述实体在给定时间点的状态,所有事件上下文都存在于有效负载中。它们很有趣,因为消息本身代表了服务和消费者之间的契约。它们可用于在业务域之间传达状态更改,其中可能希望在消费者处理消息期间存在所有事件上下文。
优点:
缺点:
将事件命名为“CustomerUpdate”并仅包含真正已更新的信息
我们称这种模式为Delta消息。
Delta 在许多方面类似于胖消息,尽管它们的生成和使用通常更复杂。JSONPatch标准就是一个很好的例子。
因为它们只是事件实体的部分描述,所以增量还带有一个内置假设,即消费者对所描述的事件有所了解。由于这个原因,它们可能不太适合在事件实体可能不为人所知的业务域之外发送。
当在共享相同实体模型的系统之间同步数据时,Deltas 真的很出色,理想情况下,它们保存在非关系存储(例如,no-sql)中。在这种情况下,可以检索实体,应用增量,然后以最小的努力再次持久化。
优点:
缺点:
将事件命名为“CustomerUpdate”并包含最少信息(标识符)和/或 URI,以让消费者检索有关此客户的信息。
让我们称之为Skinny消息。
Skinny 消息与您定义的其他消息模式不同,因为服务/消费者合同在消息中不再显式,而是暗示在稍后的某个时间消费者将检索事件上下文。这将合约和消息交换解耦,这是一件好事。
这可能适合也可能不适合跨业务领域的事件通信,具体取决于您的企业是如何设置的。因为事件有效负载非常小(通常是带有一些标头的 ID),所以除了事件名称之外没有其他上下文,消费者可以根据该名称做出处理决策;因此,确保正确命名事件变得更加重要,特别是如果消费者可以通过多种方式处理CustomerUpdated消息。
此外,在事件数据中包含实际资源地址可能不是一个好习惯 - 因为事件是已经发生的事情,事件消息通常是不可变的,因此事件中的任何信息都应该永远是真实的,以防事件需要重播。在这种情况下,资源地址很容易过时,并且事件将无法重播。
优点:
缺点:
发起事件时,哪种模式最适合?
我认为这个问题的答案是:这取决于很多事情,而且可能没有一个正确的答案。
评论更新:也值得一读,一篇关于消息传递的非常古老、经典的博文:https ://docs.microsoft.com/en-gb/archive/blogs/nickmalik/killing-the-command-message-should-we -use-events-or-documents(也在这里:http: //vanguardea.com/killing-the-command-message-should-we-use-events-or-documents/)
Martin Fowler 做了一场精彩的演讲“事件驱动架构的许多意义”(内容基于这篇论文),其中他提到了事件承载状态转移模式。
它似乎接近您的第二个选项“Delta 消息”,不同之处在于它不尝试描述实体,而是描述发生的命名业务事实并结转所有必要的数据以理解这一事实。
在设计领域事件时,我认为如何为持久层建模并不重要。同样,我认为您的消费者在设计域事件时如何建模自己的持久层并不重要。
因此,我认为将您可以将事件作为补丁直接应用于您的数据(从消费者的角度来看)这一事实作为优势并不明智,因为它会推动生产者在考虑到持久性的情况下设计他们的事件消费者模型。
在这种情况下,我倾向于认为您正在设计持久性补丁,而不是领域事件。
你怎么看?