在pub / sub模型中,如何根据某些外部状态进行Subscriber暂停处理?

时间:2014-07-25 00:35:04

标签: nservicebus

我的要求是让订阅服务器暂停处理邮件,具体取决于Web服务是否已启动。因此,当Web服务关闭时,消息应继续从发布服务器进入订户队列并继续堆积,直到Web服务再次启动。 (这些消息不应该转到错误队列,而是保留在订购者队列中。)

我尝试使用取消订阅,但发布商停止发送消息,因为取消订阅似乎清除了RavenDB上的订阅信息。我还尝试在Transport类上设置MaxConcurrencyLevel,如果我将工作线程设置为0,则发送到Subscriber的消息将直接转到错误队列。最后,我尝试了Defer,它似乎将当前消息放入审计队列并创建消息的克隆,并在超时完成时将其本地发送到订户队列。此外,由于我必须不断检查服务状态并继续推迟,我无法控制消息的顺序,因为我无法预测何时Web服务将会启动。

实现我所解释的行为的最佳方法是什么?我使用的是NServiceBus 4.5版。

2 个答案:

答案 0 :(得分:0)

听起来你想继续尝试处理消息,直到它成功,而不是将其重新排入队列(保持在顶部并继续尝试)?

我认为您唯一的纯NSB选项是修改MaxRetries设置,该设置控制第一级重试:http://docs.particular.net/nservicebus/msmqtransportconfig。将MaxRetries设置为一个非常高的数字可能会做你想要的,但我无法想象这样做是一个很好的做法。

二级重试会将消息推迟一段可配置的时间,但IIRC将允许从主队列处理其他消息。

我认为您最好的选择是将重试逻辑放入您自己的代码中。因此,处理程序可以尝试在循环(可能是延迟)中多次访问服务x,然后抛出异常并启动NSB的重试功能。

修改

您的要求似乎如下:

“当一个MyEvent进来时,我需要进行一次web服务调用。如果web服务出现故障,我需要在Y时间间隔内继续尝试X次,此时我会认为它失败并处理失败在我成功或失败之前,我将阻止处理其他消息。“

您在处理消息时有一些潜在的复杂逻辑(重试,超时,错误情况,阻止其他消息等)。请记住NSB打算在您的系统中发挥的作用:通过消息传递服务之间的通信。虽然NSB确实有一些允许消息编排的高级功能(例如sagas),但它并不是真正用于替换域或应用程序逻辑。

最重要的是,您可能需要编写自定义代码来处理您的特定方案。一个天真的解决方案是在你的处理程序中有一个延迟的循环,但你可能需要创建一个更强大的内存中的集合/队列,在服务关闭时保存消息并在它恢复时按顺序处理它们。

答案 1 :(得分:0)

实现某种必要行为的最简单方法如下:

定义一个消息处理程序,用于检查服务是否可用,如果没有,则调用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>());
     }
}

通过该设计,您将获得以下成果:

  • 您可以在调用实际业务代码之前检查可用性
  • 如果该服务不可用,则将该消息放回队列
  • 如果服务可用且您的业务代码被调用,但在调用ActualHandler之前服务变得不可用,您将获得第一级和第二级重试(以及管道中的可用性检查)