将事件命名为“CustomerUpdate”
首先让我们从您的活动名称开始。事件的目的是描述已经发生的事情。这与命令不同,命令是针对尚未发生的事情发出指令。
您的事件名称“CustomerUpdate”在这方面听起来模棱两可,因为它可能描述过去的某事或未来的某事。
CustomerUpdated 会更好,但即便如此,Updated 也是另一个模棱两可的术语,在业务环境中是不具体的。为什么在这种情况下更新了客户?是因为他们更改了付款细节吗?搬家了?他们是从白银升级到黄金的吗?活动可以根据需要进行具体化。
起初这似乎是多虑了,但是当您从事件有效负载中删除数据和上下文时,事件命名变得特别相关,更倾向于 skinny 事件(您问题中的“选项 3” ,我将在下面讨论)。
这并不是说在这个粒度级别定义事件总是合适的,只是它是一个在项目早期向您开放的途径,它可能会在以后产生红利(或者可能会让您陷入困境)数以千计的事件类型)。
回到您的实际问题,让我们依次选择您的每个选项:
将事件命名为“CustomerUpdate”并包含所有信息(更新
与否)关于客户
我们把这个“模式”称为胖信息。
胖消息(也称为快照)表示所描述实体在给定时间点的状态,所有事件上下文都存在于有效负载中。它们很有趣,因为消息本身代表了服务和消费者之间的契约。它们可用于在业务域之间传达状态更改,其中可能希望所有事件上下文在消费者处理消息期间都存在。
优点:
- 自我一致 - 无需了解其他系统即可完全使用。
- 使用简单(更新插入)。
缺点:
- 脆弱 - 服务和消费者之间的契约与消息本身耦合。
- 如果消息以错误的顺序到达,很容易用旧数据覆盖当前数据(提示:您可以使用 event sourcing 模式来缓解这种情况)
- 大。
将事件命名为“CustomerUpdate”并仅包含具有
真的更新了
我们称这种模式为 Delta 消息。
Delta 在很多方面都类似于胖消息,尽管它们的生成和使用通常更复杂。 JSONPatch 标准就是一个很好的例子。
因为它们只是事件实体的部分描述,增量也带有一个内置假设,即消费者对所描述的事件有所了解。由于这个原因,它们可能不太适合在事件实体可能不为人所知的业务域之外发送。
当在共享相同实体模型的系统之间同步数据时,Deltas 真的很出色,理想情况下是持久保存在非关系存储中(例如,no-sql)。在这种情况下,可以检索实体,应用增量,然后以最小的努力再次持久化。
优点:
- 比胖消息更小
- 在涉及共享实体模型的用例中表现出色
- 可移植(如果基于 jsonpatch 等标准,或在较小程度上基于 diffgram)
缺点:
- 类似于 Fat 消息,假设完全了解数据实体。
- 很容易用旧数据覆盖当前数据。
- 生成和使用复杂(特定用例除外)
将事件命名为“CustomerUpdate”并包含最少信息
(标识符)和/或让消费者检索信息的 URI
关于这个客户。
我们称其为 Skinny 消息。
Skinny 消息与您定义的其他消息模式不同,因为服务/消费者合同不再在消息中明确显示,而是暗示在稍后消费者将检索事件上下文。这将合约和消息交换解耦,这是一件好事。
这可能适合也可能不适合跨业务域的事件通信,具体取决于您的企业的设置方式。因为事件有效负载非常小(通常是带有一些标头的 ID),所以除了事件名称之外没有其他上下文,消费者可以根据该名称做出处理决策;因此,确保正确命名事件变得更加重要,尤其是当消费者可以通过多种方式处理 CustomerUpdated 消息时。
此外,在事件数据中包含实际资源地址可能不是一个好习惯 - 因为事件是已经发生的事情,事件消息通常是不可变的,因此事件中的任何信息都应该永远真实,以防事件发生需要重播。在这种情况下,资源地址很容易过时,事件将无法重播。
优点:
- 将服务合同与消息分离。
- 事件名称中包含有关事件的信息。
- 自然幂等(带时间戳)。
- 通常很小。
- 生成和使用简单。
缺点:
- 消费者必须进行额外调用以检索事件上下文 - 需要明确了解其他系统。
- 事件上下文在消费者检索它时可能已经过时,因此这种方法通常不适合某些实时应用程序。
在引发事件时,哪种模式最适合?
我认为这个问题的答案是:这取决于很多事情,而且可能没有一个正确的答案。
来自 cmets 的更新:也值得一读,一篇关于消息传递的非常古老的经典博文: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/)