消息类型:消息应包含多少信息?

tsi*_*lar 4 domain-driven-design message-queue integration-patterns rabbitmq

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

总体思路/架构如下:

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

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

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

    • 优点

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

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

    • 优点

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

      • 更大的消息负载
      • 不太纯净

您会推荐一种方法而不是另一种方法吗?

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

Voi*_*son 5

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

您还可以考虑不要从充当该业务部分的技术权威的服务中泄露信息

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

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

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

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

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

也就是说,如果需要状态,就需要历史(完整的、有序的)。所有单个事件真正告诉您的是历史记录已更改,并且您可以逐出以前缓存的历史记录。

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