使用NServiceBus进行多线程CQRS

时间:2012-07-05 06:52:21

标签: architecture nservicebus cqrs

我目前正在调查使用NServiceBus来解决以下问题。我只是想确保我不会因此而走下兔子洞。

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

我遇到的问题是,这一切在一个线程上运行良好,我不需要担心在我改变状态时锁定任何给定的聚合根。

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

基于我可以同时处理多个聚合根的事实,有一个自然的任务分解,但是我不能同时为同一个聚合根处理多个消息,因为这会导致高争用由于收到邮件的速度。

我试图避免我需要锁定特定聚合根id并将聚合根分配给队列/线程/进程的情况,这将确保同步处理来自同一聚合根的所有消息。 / p>

我正在使用带有NServiceBus的Pub / Sub模型来发布事件。就我看来,问题是这些事件需要从同一端点发布,即使该消息的处理可能被委托给另一个端点。即我需要欺骗系统认为该消息是从“MyDomainQueue”发布的,而实际上该消息是在“MyDomainQueue-Worker1”上处理的。

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

我正在寻找有关此方法的一些反馈。感觉我工作有点难以让这个工作,我只是想检查是否有其他人处理过类似的问题。也许NServiceBus是错误的工具,或者我的方法可能是错的。欢迎提出任何反馈意见。

谢谢,

PS - 我也担心上述解决方案所需的配置数量。

1 个答案:

答案 0 :(得分:1)

关于从不同端点发布事件,我认为你有点过于关注从一个服务发布的事件的概念。仅在逻辑意义上这是真的 - 一个事件应该由一个逻辑服务完全拥有,但是逻辑服务可以由许多端点组成

事件并非真正从队列中发布。当您想到发布事件的队列时,您真正在谈论的是您发送该事件的订阅请求的输入队列。

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

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

那就是说,你试过让多个线程访问聚合根吗?即使有一些争论,你可能会发现,通过少量的重试,它可能不像你想象的那样有争议。我在NServiceBus的生产过程中有一些相当有争议的过程,虽然我偶尔看到争用的证据是日志中的异常,有5次重试,我从来没有任何进展到错误队列。

- 最近,添加了第二级重试功能,这进一步降低了消息在错误队列中结束的可能性。

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