Nservicebus 在发布/订阅模型中,如何基于某些外部状态进行订阅者暂停处理?
我的要求是让订户暂停处理消息,这取决于web服务是否启动。因此,当web服务关闭时,消息应该不断从发布服务器到达订户队列,并不断堆积,直到web服务再次启动。(这些消息不应转到错误队列,而应留在订户队列上。) 我试图使用unsubscribe,但发布者停止发送消息,因为unsubscribe似乎清除了RavenDB上的订阅信息。我还尝试在传输类上设置MaxConcurrencyLevel,如果我将工作线程设置为0,则到达订阅者的消息将直接进入错误队列。最后,我尝试了Defer,它似乎将当前消息放在审核队列中,并创建消息的克隆,并在超时完成时将其本地发送到订户队列。此外,由于我必须不断检查服务状态并不断延迟,我无法控制消息的顺序,因为我无法预测web服务何时启动Nservicebus 在发布/订阅模型中,如何基于某些外部状态进行订阅者暂停处理?,nservicebus,Nservicebus,我的要求是让订户暂停处理消息,这取决于web服务是否启动。因此,当web服务关闭时,消息应该不断从发布服务器到达订户队列,并不断堆积,直到web服务再次启动。(这些消息不应转到错误队列,而应留在订户队列上。) 我试图使用unsubscribe,但发布者停止发送消息,因为unsubscribe似乎清除了RavenDB上的订阅信息。我还尝试在传输类上设置MaxConcurrencyLevel,如果我将工作线程设置为0,则到达订阅者的消息将直接进入错误队列。最后,我尝试了Defer,它似乎将当前消息放
实现我所解释的行为的最佳方式是什么?我使用的是NServiceBus版本4.5 听起来您想一直尝试处理消息,直到消息成功为止,而不是将其拖回队列中(保持在顶部并继续尝试) 我认为您唯一的纯NSB选项是修改MaxRetries设置,它控制第一级重试:。将MaxRetries设置为一个非常高的数字可能会满足您的需求,但我无法想象这样做会是一个好的实践 第二级重试将延迟消息一段可配置的时间,但IIRC将允许从主队列处理其他消息 我认为您最好的选择是将重试逻辑放入您自己的代码中。因此,在抛出异常和NSB的重试功能开始之前,处理程序可以尝试在一个循环中访问服务x多次(可能是延迟) 编辑: 您的要求似乎是: 当一个MyEnter进来时,我需要做一个WebService调用。如果WebService被关闭,我需要在Y区间上尝试X次,在这一点上,我会认为它是一个失败并处理一个失败的条件。直到我成功或失败,我将阻止其他消息被处理。 您在处理消息时有一些潜在的复杂逻辑(重试、超时、错误条件、阻止其他消息等)。请记住NSB打算在您的系统中扮演的角色:通过消息传递在服务之间进行通信。虽然NSB确实有一些允许消息编排的高级功能(如sagas),但它并不是真正用来取代域或应用程序逻辑的
总之,您可能需要编写自定义代码来处理特定场景。一个简单的解决方案是处理程序中有延迟的循环,但您可能需要创建一个更健壮的内存中收集/队列,在服务关闭时保存消息,并在服务恢复时串行处理消息。实现所需行为的最简单方法如下: 定义检查服务是否可用的消息处理程序,如果不可用,则调用HandleCurrentMessageLater和执行实际消息处理的消息处理程序。然后指定消息处理程序顺序,以便首先执行检查服务可用性的处理程序
public interface ISomeCommand {}
public class ServiceAvailabilityChecker : IHandleMessages<ISomeCommand>{
public IBus Bus { get; set; }
public void Handle(ISomeCommand message) {
try {
// check service
}
catch(SpecificException ex) {
this.Bus.HandleCurrentMessageLater();
}
}
}
public class ActualHandler : IHandleMessages<ISomeCommand>{
public void Handle(ISomeCommand message) {
}
}
public class SomeCommandHandlerOrdering : ISpecifyMessageHandlerOrdering{
public void SpecifyOrder(Order order){
order.Specify(First<ServiceAvailabilityChecker>.Then<ActualHandler>());
}
}
公共接口命令{}
公共类服务可用性检查:IHandleMessages{
公共IBus总线{get;set;}
公共无效句柄(命令消息){
试一试{
//支票服务
}
捕获(特殊异常){
this.Bus.HandleCurrentMessageLater();
}
}
}
公共类实际句柄:IHandleMessages{
公共无效句柄(命令消息){
}
}
公共类SomeCommandHandlerOrdering:isSpecifyMessageHandlerOrdering{
公共无效指定人(订单){
order.Specify(First.Then());
}
}
通过这种设计,您可以获得以下好处:
- 您可以在调用实际业务代码之前检查可用性
- 如果服务不可用,则将消息放回队列
- 如果服务可用,并且您的业务代码被调用,但就在调用ActualHandler之前,服务变得不可用,您将获得第一级和第二级重试(以及管道中的可用性检查)