我目前正在研究使用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/