在NServiceBus 3+中使用超时管理器与分发服务器的正确方法是什么?

jan*_*esk 7 nservicebus nservicebus-distributor nservicebus3

3版之前的建议是在分发服务器旁边运行超时管理器作为群集上的独立进程.(详见此处:http://support.nservicebus.com/customer/portal/articles/965131-deploying-nservicebus-in-a-windows-failover-cluster).

在将超时管理器作为附属程序集包含之后,在与分发服务器进行扩展时使用它的正确方法是什么?

服务A的每个工作程序是否应该在启用超时管理器的情况下运行,或者只应将服务A的分发程序进程配置为运行服务A的超时管理器?

如果每个工作者都运行它,他们是否共享相同的Raven实例来存储超时?(如果是这样,你如何确保两个或多个工人同时没有获得相同的过期超时?)

jan*_*esk 10

请允许我自己清楚地回答这个问题.

经过大量挖掘并在安德鲁斯·奥伦德的帮助下,在NSB团队(http://tech.groups.yahoo.com/group/nservicebus/message/17758)上,对这个问题的正确解答是:

  • 与Udi Dahan提到的一样,只有设计者才能在分出场景中运行超时管理器.
  • 不幸的是,在NServiceBus 3的早期版本中,这并未按设计实现.

您有以下3个问题:

1)使用分发服务器配置文件运行不会启动超时管理器.

解决方法:

通过在分发服务器上包含此代码,自行启动分发服务器上的超时管理器:

class DistributorProfileHandler : IHandleProfile<Distributor> 
{
   public void ProfileActivated()
   {
       Configure.Instance.RunTimeoutManager();
   }
}
Run Code Online (Sandbox Code Playgroud)

如果您运行主配置文件,这不是问题,因为主节点上的超时管理器会自动启动.

2)使用Worker配置文件DO运行的工作程序每个都启动本地超时管理器.

这不是设计的,并且会对超时存储和超时调度进行轮询.所有工作人员都会在"给我即将到来的MASTERNODE超时"的情况下对超时存储进行轮询.请注意,他们要求MASTERNODE超时,而不是W1,W2等等.因此,几个工作人员最终会同时从超时存储中获取相同的超时,从而导致与Raven的删除超时时发生冲突.

调度始终通过LOCAL .timouts/.timeoutsdispatcher队列进行,而它应该通过MasterNode/Distributor上的超时管理器的队列.

解决方法,您需要同时执行以下两项操作:

a)禁用worker上的超时管理器.将此代码包含在您的员工中

class WorkerProfileHandler:IHandleProfile<Worker>
{
    public void ProfileActivated()
    {
        Configure.Instance.DisableTimeoutManager();
    }
}
Run Code Online (Sandbox Code Playgroud)

b)重新对工作人员进行NServiceBus,以便在MasterNode/Distributor上使用.timeouts队列.

如果你不这样做,任何对工作者的RequestTimeout或Defer的调用将会因为你忘记配置超时管理器而异常死亡.将其包含在您的工作程序配置中:

<UnicastBusConfig TimeoutManagerAddress="{endpointname}.Timeouts@{masternode}" /> 
Run Code Online (Sandbox Code Playgroud)

3)错误的"就绪"消息返回分销商.

由于超时管理器直接将消息调度到工作者输入队列而不从分发服务器存储队列中的可用工作程序中删除条目,因此工作程序在处理超时后将错误的"就绪"消息发送回分发服务器.即使您已经修复了1和2,也会发生这种情况,如果从工作服务器上的本地超时管理器或分发服务器/ MasterNode上运行的超时管理器获取超时,则没有任何区别.结果是,对于工作人员处理的每个超时,在分发服务器上的存储队列中建立额外条目.

解决方法:使用NServiceBus 3.3.15或更高版本.