c# - CQRS 的事件总线

标签 c# cqrs

我用 CQRS 编写了一个项目。我想从域事件异步构建我的读取模型。当我阅读 Greg Young 和其他有关 CQRS 的主题时,我发现只需使用服务总线即可。但对我来说,服务总线是消息传输的技术层,在这种情况下,处理顺序并不重要。

域事件是具有特殊性的消息:处理顺序很重要。

那么,我是否使用带有附加(复杂)层的服务总线(NServiceBus、公共(public)交通...)来确保事件处理顺序?或者具有这种特殊性的特定“事件总线”已经存在?

编辑

我更准确地解释我的情况:

我使用 CQRS 进行了第一个应用程序。在此应用程序中,我使用关系数据库作为持久层,而不是事件源。该数据库用于写入端和读取端。这是一个选择。此应用程序在抽象总线上发布域事件,但没有实现。

我需要创建第二个应用程序,并从第一个应用程序中读取模型构建。

在这种情况下,如果我使用事件存储,那么使用事件存储为我的第二个应用程序构建投影是一件坏事。如果持久层发生变化,其他应用程序(监听器)就会受到影响。

编辑 2:解决方案?

解决方案可能是使用事件存储/服务总线这对来构建事件总线。因此,持久性无知被保留,事件总线作为构建投影和监听事件的工具。

编辑3:GetEventStore

我查看了GetEventStore,它提供了订阅机制。 解决方案可能是使用 GetEventStore 作为事件总线!

所以如果我使用 GetEventStore 作为事件总线,这意味着我使用事件源?或者事件溯源只是持久层的一个概念?或者在我的第一个应用程序中,我已经使用事件源,因为我使用聚合中的域事件来构建关系数据库中的状态?

所以新的问题是什么是事件溯源?直接将事件存储在事件存储中还是使用域事件来构建状态?

最佳答案

这里有几件事需要考虑。

如果您使用事件溯源,您可能需要使用 GES (geteventstore.com)。在这种情况下,用于构建读取模型的事件不会通过任何消息总线,而是使用订阅从事件存储中检索。在这种情况下,您总是会得到正确的订单。

如果“普通”数据库中只有两个独立的模型,这是文档数据库还是关系数据库,您可能应该使用一些消息总线。这里还有一些事情:

  • 请记住,更新写入端并将事件发布到消息总线应在事务中完成。否则,您的读取模型将面临不一致的风险

  • NServiceBus 或 MassTransit 没有作为服务总线抽象来处理消息排序。事实上,您应该选择正确的交通工具,它就能完成任务。例如,AMQP 对消息排序设置了一些要求,RabbitMQ delivers 。当然,总的来说,使用 NSB 或 MT 会让你的生活变得更轻松,但这是完全不同的事情

  • 通过将聚合版本保留为两侧的字段,您始终可以将写入端和读取端保持在同一版本上。在这种情况下,您至少可以知道是否收到一些有间隙的事件并决定该怎么做 - 等待丢失的事件被传递或只是停止处理并崩溃以允许手动干预

实践表明,所有现代经纪商都支持 AMQP 并遵循标准。虽然您可能有重复项,但这危险性要小得多。

您可以选择使用 ZMQ,这将为您带来几乎零延迟,因此,除非您的数据量非常高,否则无序传送消息的变化将是微不足道的。

关于c# - CQRS 的事件总线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37744410/

相关文章:

c# - 在 KeyValuePair 列表中查找重复键

c# - Lerp 颜色基于 2 个对象之间的距离

c# - 运算符 '?' 不能应用于类型 'T' 的操作数

c# - Quartz.NET 的闭源替代品

domain-driven-design - CQRS:写入模型可以使用读取模型吗?

rest - CQRS 和 REST HATEOAS 不匹配

c# - 如何在 datagrid C# wpf 中动态行?

api - 一起执行REST,CQRS和EventSourcing时如何在REST中支持Command?

swift - 我可以使一个结构或类多次符合通用协议(protocol)吗?

cqrs - 事件溯源 - 事件重放