architecture - 使用NServiceBus的多线程CQRS

标签 architecture nservicebus cqrs

我目前正在研究使用NServiceBus解决以下问题。我只想确保我不会因此而陷入困境。

我有一个基于CQRS架构的解决方案。本质上,我有一系列通过NServiceBus传递到端点的命令,我执行一些处理以更改聚合根的状态,然后触发一系列事件以将更改通知给系统的其余部分。

我的问题是,这一切都可以在一个线程上很好地起作用,在我更改状态时,我不必担心锁定任何给定的聚合根。

我们已经到了一个线程无法削减的地步,我需要开始研究使用多个工作线程/进程来处理消息。

我可以同时处理多个聚合根,但我无法同时处理多个消息,因此我无法同时处理多个消息,因为这会导致高竞争接收邮件的速度。

我试图避免这种情况,我需要锁定特定的聚合根ID,而是将聚合根分配给队列/线程/进程,以确保来自同一聚合根的所有消息都得到同步处理。

我正在使用带有NServiceBus的发布/订阅模型来发布事件。就我所知,问题是这些事件需要从同一端点发布,即使该消息的处理可能委派给另一个事件也是如此。即我需要诱使系统以为该消息是从“MyDomainQueue”发布的,而实际上是在“MyDomainQueue-Worker1”上处理了该消息。

我的计划是创建一个自定义分发程序,该分发程序将允许主端点将消息的处理委派给工作端点。分发者将以循环方式为任何给定聚合根分配一个队列。主端点将向这些工作程序发送命令,然后进行处理,工作程序将回复事件列表。然后,主要端点将事件发布回总线上。

我正在寻找有关此方法的一些反馈。感觉我在努力工作以使它起作用,我只想检查是否还有其他人处理过类似的问题。也许NServiceBus是工作的错误工具,或者我的方法是错误的。任何反馈都是欢迎的。

谢谢,

PS-我也对上述解决方案所需的配置量感到担忧。

最佳答案

关于从不同终结点发布事件,我认为您对从一个服务发布事件的概念有些不知所措。仅从逻辑上讲是正确的-一个事件应完全由一个逻辑服务完全拥有,但是一个逻辑服务可以由许多端点组成。

事件实际上不是从队列中发布的。当您想到发布事件的队列时,您真正在说的是输入队列,您可以在该队列中发送该事件的订阅请求。

因此,您可以让多个端点都发布同一事件,只要该事件的订阅请求都到达同一位置即可。

这是常见的情况,例如,在批量与优先级​​方案中,您有两个端点处理相同的命令(然后发布相同的事件),除了一个端点的SLA较长,而另一个端点的SLA则短得多SLA-也许是大客户,或者命令来自等待响应的实际人类用户。 QueueA和PriorityQueueA都处理相同的命令并发布相同的事件,但是QueueA处理订阅,因此这两个进程都从QueueA“发布”。

也就是说,您是否尝试过让多个线程访问聚合根?即使存在某些争用,您也可能会发现重试次数很少,可能没有您想象的那么有争议。我在使用NServiceBus的生产中有一些相当有争议的过程,尽管我偶尔看到争用的证据是日志中的异常,但是在进行5次重试后,我从来没有任何进展到错误队列。

-最近,添加了第二级重试功能,这进一步减少了消息在错误队列中结束的机会。

如果存在太多争用,另一种策略可能是维护当前正在操作的聚合根的内存列表,然后,如果出现一条消息应“锁定”,则只需调用Bus.HandleCurrentMessageLater()将该消息重新粘贴到队列结束。

关于architecture - 使用NServiceBus的多线程CQRS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11339165/

相关文章:

domain-driven-design - DDD\ES\CQRS 中应用程序的 CRUD 部分

database - 如何在 C* (Cassandra) 中执行高效的 SELECT * 查询

java - REST - 应用层还是服务层?

c# - NServiceBus 异常和订阅者无法读取队列

c# - 从队列中选择性读取-自定义MSMQ服务,ESB还是其他内容?

message-queue - 尝试使用Nservicebus时发生错误

domain-driven-design - 在使用事件溯源时使用聚合版本号是幂等的

c# - 这是与 Entity Framework 交互的正确方式吗?

architecture - 自上而下还是自下而上的设计?

domain-driven-design - 微服务之间基于事件的通信没有共享事件库?