events - 事件驱动架构和事件结构

标签 events architecture soa event-driven eda

我是 EDA 的新手,我已经阅读了很多关于好处的内容,并且可能有兴趣在我的下一个项目中应用它,但仍然没有理解。

引发事件时,哪种模式最适合:

  • 将事件命名为“CustomerUpdate”并包含有关客户的所有信息(更新与否)
  • 将事件命名为“CustomerUpdate”并仅包含真正更新的信息
  • 将事件命名为“CustomerUpdate”并包含最少信息(标识符)和/或 URI,以让消费者检索有关此客户的信息。

  • 我问这个问题是因为我们的一些事件可能是沉重和频繁的。

    感谢您的回答和时间。

    最佳答案

    Name the event "CustomerUpdate"


    首先让我们从您的事件名称开始。事件的目的是描述已经发生的事情。这与命令不同,命令是针对尚未发生的事情发出指令。
    在这方面,您的事件名称“CustomerUpdate”听起来模棱两可,因为它可能描述过去或 future 的某些事情。
    CustomerUpdated 会更好,但即便如此,Updated 也是另一个模棱两可的术语,并且在业务上下文中是非特定的。为什么在这种情况下更新了客户?是因为他们更改了付款详细信息吗?搬家了?他们是否从白银升级为黄金状态?可以根据需要根据具体情况制作事件。
    乍一看,这似乎是多虑了,但是当您从事件有效负载中删除数据和上下文时,事件命名变得尤为重要,更多地转向瘦事件(您的问题中的“选项 3”,我将在下面讨论)。
    这并不是说在这个粒度级别定义事件总是合适的,只是它是一个在项目早期向您开放的途径,可能会在以后支付红利(或者可能让您淹没在数以千计的事件中)类型)。
    回到您的实际问题,让我们依次考虑您的每个选项:

    Name the event "CustomerUpdate" and include all information (updated or not) about the customer


    让我们称这种“模式”为 Fat 消息。
    胖消息(也称为快照)表示所描述实体在给定时间点的状态,所有事件上下文都存在于有效负载中。它们很有趣,因为消息本身代表了服务和消费者之间的契约。它们可用于在业务域之间传达状态变化,在这种情况下,消费者最好在消息处理期间提供所有事件上下文。
    好处:
  • 自我一致 - 可以在不了解其他系统的情况下完全使用。
  • 易于使用(upsert)。

  • 缺点:
  • 脆弱 - 服务和消费者之间的契约与消息本身耦合。
  • 如果消息以错误的顺序到达,很容易用旧数据覆盖当前数据(提示:您可以使用 event sourcing 模式来缓解这种情况)
  • 大的。

  • Name the event "CustomerUpdate" and include only information that have really been updated


    我们将此模式称为 Delta 消息。
    Deltas 在很多方面类似于胖消息,尽管它们的生成和消费通常更复杂。这里的一个很好的例子是 JSONPatch标准。
    因为它们只是事件实体的部分描述,增量还带有一个内置假设,即消费者对所描述的事件有所了解。出于这个原因,它们可能不太适合在业务领域之外发送,在那里事件实体可能并不为人所知。
    在共享相同实体模型的系统之间同步数据时,Delta 真的很出色,理想情况下,它可以持久保存在非关系存储(例如,no-sql)中。在这种情况下,可以检索实体,应用增量,然后以最小的努力再次持久化。
    好处:
  • 小于 Fat 消息
  • 在涉及共享实体模型的用例中表现出色
  • 便携(如果基于 jsonpatch 等标准,或者在较小程度上基于 diffgram)

  • 缺点:
  • 与 Fat 消息类似,假定数据实体的完整知识。
  • 很容易用旧数据覆盖当前数据。
  • 生成和使用的复杂性(特定用例除外)

  • Name the event "CustomerUpdate" and include minimum information (Identifier) and/or a URI to let the consumer retrieves information about this Customer.


    让我们称之为瘦消息。
    瘦消息与您定义的其他消息模式不同,因为服务/消费者契约(Contract)在消息中不再是明确的,而是暗示消费者稍后将检索事件上下文。这将合约和消息交换解耦,这是一件好事。
    这可能适合也可能不适合事件的跨业务领域通信,具体取决于您的企业是如何设置的。由于事件负载非常小(通常是带有一些 header 的 ID),除了事件名称之外,没有其他上下文可供消费者做出处理决策;因此,确保正确命名事件变得更加重要,特别是如果消费者可以通过多种方式处理 CustomerUpdated 消息。
    此外,在事件数据中包含实际资源地址可能不是一个好习惯——因为事件是已经发生的事情,事件消息通常是不可变的,因此事件中的任何信息都应该永远真实,以防事件需要重播。在这种情况下,资源地址很容易过时,事件将无法重播。
    好处:
  • 将服务契约与消息解耦。
  • 事件名称中包含的有关事件的信息。
  • 自然幂等(带时间戳)。
  • 一般很小。
  • 易于生成和使用。

  • 缺点:
  • 消费者必须进行额外的调用以检索事件上下文 - 需要其他系统的明确知识。
  • 事件上下文在消费者检索它时可能已经过时,使得这种方法通常不适用于某些实时应用程序。

  • When raising an event, which pattern is the most suited?


    我认为这个问题的答案是:这取决于很多事情,而且可能没有一个正确的答案。
    评论更新:同样值得一读,一篇关于消息传递的非常古老的经典博客文章: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/ )

    关于events - 事件驱动架构和事件结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34545336/

    相关文章:

    javascript - onchange 事件运行不正常

    c# - 为什么我不能直接将自定义事件参数类传递到订阅我的事件的方法中?

    c# - .NET Architectural issue : 2 Web Services, 如何更改在运行时使用哪一个?

    c# - 分离接口(interface)和构造函数注入(inject)

    c# - Thrift 中缺少 "objects"是不是很尴尬?

    java - DTO应该使用继承还是组合

    c++ - QGraphicsWidget 的上下文菜单事件

    architecture - 游戏对象绘制和更新自身的架构有什么问题?

    wcf - 在 Azure 中托管超过 25 个 WCF 服务

    .net - .net 中的事件签名模式