【问题标题】:How can I avoid repeating type definitions in an event sourced, event-driven architecture with CQRS?如何避免在使用 CQRS 的事件源、事件驱动架构中重复类型定义?
【发布时间】:2021-02-01 02:32:59
【问题描述】:

情况

为了更好地理解 CQRS、事件溯源和异步服务通信的概念,我一直在使用 Go、MongoDB 和 RabbitMQ 构建一个小型系统。这包括以下内容:

  • 命令 API:公开 API 以接受和处理命令,然后将事件写入 MongoDB 集合(称为“事件”)
  • 事件发布者:监视“事件”集合的变化并将其发布到 RabbitMQ
  • 事件消费者:从 RabbitMQ 接收事件并使用它们来更新读取优化的 MongoDB 集合
  • 查询 API:公开 API 以从具体化集合返回数据

(我设想为系统中的每个微服务重复一组类似的应用程序,所有应用程序都通过 RabbitMQ 异步通信)

问题

我觉得我在高层次上对这些概念有了不错的掌握,但是在构建这个系统时,我在细节上遇到了一些麻烦。我发现我需要:

  1. 使用 BSON 作为 RabbitMQ 有效负载,使事件发布者的事情变得“简单” - 这感觉就像 MongoDB 正在泄漏到设计的其余部分,因为否则我不会选择 BSON

  2. 让事件发布器了解所有事件类型,以便它可以正确地将存储的事件从 BSON 转换为 JSON(例如,将日期和 UUID 重写为字符串)以发布到消息总线 - 这似乎很臭,因为各种事件类型需要在不少于三个不同的地方定义(命令端、查询端、事件发布者)。

问题

  1. 这种类型的问题对于使用 CQRS + 事件溯源 + 消息总线的设计来说是正常现象,还是我的方法存在根本缺陷?

  2. 如果这是课程的标准,那么以上两个选项中哪一个更适合用于生产环境?

我的搜索没有发现任何关于这个问题的信息,但如果你知道一篇文章或博客文章解决了这个问题,那可能就足够了。

【问题讨论】:

    标签: mongodb go rabbitmq cqrs event-sourcing


    【解决方案1】:

    有事件升级者的概念。事件升级器的目的是在发布事件之前(也在聚合水化之前)将来自事件存储的事件作为非类型化数据结构转换为类型化数据结构。这些通常用于版本控制。请记住,系统越多,您的事件类型更改的机会就越多,因此您将无法仅从 json/bson 反序列化。

    一旦你输入了正确的事件,在 json 中将它们序列化以将它们传递到总线并在另一端反序列化它们。

    事件类型需要在不少于三个不同的地方定义(命令端、查询端和事件发布者)

    只需在共享库中定义您的事件类型。

    另外,它不相关,但你真的不需要公共汽车。当涉及到重建投影时,它们会导致更多问题,因为它们不会跟踪上次读取事件。 Greg Young 在 YouTube 的某个地方谈到了它(应该不难找到)。

    【讨论】:

    • 有趣,我没有听说过事件升级器的这个概念。对于这个应用程序,我意识到消息总线严重过度,但我想了解如何将其构建为更复杂系统的一部分。不过,我会研究 Greg Young 的谈话,以防它比我意识到的更多。谢谢!
    • 至于共享库,我的印象是那是不可取的,但我认为我混淆了这种情况,即各个部分由一个团队拥有,与库的情况可能会在团队之间共享,从而在团队之间创建依赖关系。
    • 我理解你的挣扎,但在某些时候你必须在服务和事件之间建立合同是完美的选择。您还可以在双方使用事件升级程序,以最大程度地减少事件合同中断更改的影响。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 1970-01-01
    • 2021-12-29
    相关资源
    最近更新 更多