支持 Axon 或 Kafka CQRS/ES

Axon or Kafka to support CQRS/ES

考虑我想将产品评分作为事件存储在事件存储中的简单用例。

我可以使用两种不同的方法:

  1. 使用Axon:Rating 聚合负责处理CreateRatingCommand 并发送RatingCreatedEvent。发送事件将使评级存储在事件存储中。其他事件处理程序有可能在连接到 Axon 服务器实例时重播事件流,并根据评级做任何需要的事情。在这种情况下,事件处理程序将用作流处理器。
  2. 使用Kafka:KafkaProducer 将用于在 Kafka 主题中存储评级 POJO(在正确序列化后)。将主题的保留时间设置为无限期不会导致任何事件及时丢失。在这种情况下,Kafka Streams 将用于执行实际的评级处理逻辑。

对于这两种方法,我都遇到了一些架构问题:

使用Axon时:

  1. 如果聚合中没有要维护或更改的真实状态,使用 Axon(或类似解决方案)是否有任何附加值?聚合只是充当数据的“哑”占位符,但不提供任何状态更改逻辑。
  2. Axon 如何处理同一事件类型的多个事件处理程序?它们会并行处理同一个事件(相同的聚合 ID),还是同一个事件仅由其中一个处理程序处理一次?
  3. Axon 事件存储中存储的事件是否一直保存到时间结束?

使用Kafka时:

  1. Kafka 在同一个分区中存储 events/messages 相同的键。在用户产品评级的用例中,一个 select 如何获得键的最佳值? UserId、ProductId 或两者的单独主题,并在两个主题中发布每个事件。
  2. 为每个用户和每个产品使用单独的主题会导致集群上出现大量主题是否明智? (大约 <5k 产品和 >10k 用户)。

我不知道 SO 是否是此类问题的首选论坛...我只是想知道您(会)在这个特定用例中推荐什么作为最佳实践。期待您的反馈,并随时指出我在之前的问题中遗漏的其他想法。

EDIT@12/11/2020:我刚找到一个 related discussion,其中包含与我的问题相关的有用信息。

正如 Jan Galinski 已经指出的那样,这确实没有一个万无一失的答案。这值得更广泛的讨论,例如 AxonIQ's Discuss forum。无论如何,这里有一些问题我肯定可以给出答案,所以让我们开始吧:

  1. Axon 问题 1 - 正如您所注意到的,Axon Framework 大量用于以 DDD 为中心的应用程序。然而,没有什么能迫使你将自己建立在那个概念之上。您可以从事件源细节和建模细节中剥离框架,完全和纯粹地追求不同命令、事件和查询的消息传递理念。在实际发布版本 4(当前)时,将 Axon Framework 版本 3 分成这些子部分是有意识的决定。除此之外,我认为不仅仅将自己基于事件消息是很有价值的。使用不同的命令和查询只会进一步分离您的组件,从而使应用程序环境更加丰富和易于扩展。
  2. Axon 问题 2 - 这取决于 @EventHandler 注释方法的实际位置。如果它们在同一个 class 中,则只会调用一个。如果它们被定位到不同的 classes 中,那么两者将收到相同的事件。此外,如果它们在不同的 classes 之间隔离,请务必注意 Axon 使用事件处理器作为调用事件处理程序的技术解决方案。如果不同的 classes 被分组在同一个事件处理器下,您可以强加一个特定的顺序,首先调用哪个处理程序。接下来,如果事件处理应该并行发生,您将必须配置所谓的 TrackingEventProcessor(Axon 框架中的默认设置),因为它允许配置多个线程来同时处理事件。好吧,作为本节的总结,您在问题二中提出的所有问题都是一种选择,而不是必需的。真的只是配置问题。可能值得在 Axon Framework 的 this 文档页面上查看有关此事的信息。
  3. Axon 问题 3 - 由于 Axon 服务器用于事件存储,因此根本没有保留期。所以是的,默认情况下它们会一直保留到时间结束。但是,如果您觉得存储事件没有任何价值,例如将所有模型都基于(就像您在使用事件溯源时所做的那样),没有什么可以阻止您删除事件。

这是我个人不太熟悉的 Kafka 问题(我猜是 Axon Framework 的贡献者)。不过,我也可以在这里就此事给你我的两分钱,尽管我会在这里推荐第二个意见:

  1. Kafka 问题 1 - 根据我个人对此类应用程序要求的感觉,我假设您希望能够检索给定产品的所有数据尽可能高效。我敢打赌,重要的是所有事件都在同一个分区中,以使这个过程尽可能高效,之后是否不需要任何合并。考虑到这一点,我认为使用 ProductId 最有意义。
  2. Kafka 问题 2 - 如果您预计只有 5_000 产品和 10_000 用户,我想应该可以有单独的主题对于这些。 意见传入 - 虽然我个人认为 Kafka 的意图是为您提供直接权力来决定何时使用主题,而不是您实际尝试实现的目标,哪些业务复杂化功能。从应用程序开发的角度来看,赋予分离流的能力更像是事后的想法。只要您需要企业 grade/efficient 消息总线,我认为这就是该选项真正发挥作用的时候,因为那时您可以针对批量进行优化。

希望这一切能帮助你进一步@KDW!