我的要求是让订阅服务器暂停处理邮件,具体取决于Web服务是否已启动。因此,当Web服务关闭时,消息应继续从发布服务器进入订户队列并继续堆积,直到Web服务再次启动。 (这些消息不应该转到错误队列,而是保留在订购者队列中。)
我尝试使用取消订阅,但发布商停止发送消息,因为取消订阅似乎清除了RavenDB上的订阅信息。我还尝试在Transport类上设置MaxConcurrencyLevel,如果我将工作线程设置为0,则发送到Subscriber的消息将直接转到错误队列。最后,我尝试了Defer,它似乎将当前消息放入审计队列并创建消息的克隆,并在超时完成时将其本地发送到订户队列。此外,由于我必须不断检查服务状态并继续推迟,我无法控制消息的顺序,因为我无法预测何时Web服务将会启动。
实现我所解释的行为的最佳方法是什么?我使用的是NServiceBus 4.5版。
答案 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>());
}
}
通过该设计,您将获得以下成果: