4

我们目前开始将事件从一个中央应用程序广播到其他可能感兴趣的消费者应用程序,并且我们团队成员之间对于我们应该在发布的消息中放置多少有不同的选择。

总体思路/架构如下:

  • 生产者应用程序中:
    • 用户与可以创建/修改/删除的一些实体(DDD 意义上的聚合根)交互
    • 根据正在发生的事情,引发域事件(例如:EntityXCreated、EntityYDeleted、EntityZTransferred 等......即不仅是 CRUD,而且主要是)
    • 引发的事件被翻译/转换成我们发送到 RabbitMQ Exchange 的消息
  • RabbitMQ中 (我们使用的是 RabbitMQ,但我相信这个问题实际上与技术无关)
    • 我们为每个消费应用程序定义一个队列
    • 绑定将交换连接到消费者队列(可能使用消息过滤)
  • 消费应用程序中
    • 应用程序使用并处理其队列中的消息

基于企业集成模式,我们正在尝试为我们发布的消息定义规范格式,并且在两种方法之间犹豫不决:

  1. Minimalist messages / event-store-ish:对于领域模型发布的每个事件,生成一条仅包含聚合根的相关部分的消息(例如,当更新完成时,仅发布有关更新部分的信息聚合根,或多或少与最终用户在使用我们的应用程序时所经历的过程相匹配)

    • 优点

      • 小消息大小
      • 非常专业的消息类型
      • 接近“领域事件”
    • 缺点

      • 如果无法保证交货顺序(即如果在创建消息之前收到更新消息怎么办?)
      • 消费者需要知道订阅哪些消息类型(可能需要大列表/领域知识)
      • 如果消费者状态和生产者状态不同步怎么办?
      • 如何处理将来注册但不了解所有过去事件的新消费者
  2. 完全包含的幂等消息:对于域模型发布的每个事件,生成一条包含该时间点聚合根的完整快照的消息,因此实际上只处理两种消息“创建或更新”和“删除”(+元数据,如有必要,提供更具体的信息)

    • 优点

      • 幂等(声明性消息说明“事实就是这样,尽可能同步自己”)
      • 要维护/处理的消息格式数量较少
      • 允许逐步纠正消费者的同步错误
      • 只要结果消息遵循规范数据模型,消费者就会自动处理新的领域事件
    • 缺点

      • 更大的消息负载
      • 不太

你会推荐一种方法吗?

我们应该考虑另一种方法吗?

4

1 回答 1

5

我们应该考虑另一种方法吗?

您也可以考虑不将信息泄露出作为该部分业务的技术权威的服务

这大致意味着您的事件带有标识符,以便相关方可以知道感兴趣的实体已更改,并且可以查询权限以更新状态。

对于域模型发布的每个事件,生成一条消息,其中包含该时间点聚合根的完整快照

这还有一个额外的缺点,即对聚合表示的任何更改也意味着对作为 API 一部分的消息模式的更改。因此,聚合的内部更改开始跨越您的服务边界。如果您正在实施的聚合对您的业务具有竞争优势,那么您可能希望能够快速适应;涟漪增加了摩擦,会减慢你改变的能力。

如果消费者状态和生产者状态不同步怎么办?

据我所知,这个问题表明存在设计错误。如果消费者需要状态,也就是说从聚合历史构建的视图,那么它应该从生产者那里获取该视图,而不是尝试从观察到的消息集合中组装它。

也就是说,如果你需要状态,你需要历史(完整的,有序的)。一个事件真正告诉你的是历史已经改变,你可以驱逐你以前缓存的历史。

同样,对变化的响应能力:如果你改变了生产者的实现,而消费者也试图拼凑他们自己的历史副本,那么你的变化就会跨越服务边界。

于 2016-09-20T19:08:54.653 回答