我有一个web应用程序通过rebus发送消息,在远程机器上启动长时间运行的作业。我正在使用MSMQ传输。远程工作者可以并行处理5个操作。因此,如果远程工作线程很忙,一些消息可能会堆积在队列中,直到工作线程能够处理它们。同时,用户可能决定取消挂起的操作(或正在执行的操作)。当使用rebus(或任何总线)时,处理这种特殊场景的最佳策略是什么?
由于队列是不透明的,并且端点只能看到它实际尝试接收的消息,因此实际上没有办法在接收消息之前对消息进行过滤。
根据不做不必要的工作对你来说有多重要,我可以想到几种方法在处理开始之前中止它。
我能想到的一种方法是利用Rebus在处理程序管道中执行处理程序的事实,这意味着您可以在执行消息之前拦截消息。
如果你的工作是由DoWork
执行的,你可以像这样插入一个"过滤器":
Configure.With(...)
.(...)
.Options(o => o.SpecifyOrderOfHandlers()
.First<AbortIfCancelled>()
.Then<DoWork>())
.Start();
然后你的AbortIfCancelled
看起来像这样:
public class AbortIfCancelled : IHandleMessages<Work>
{
readonly IMessageContext _messageContext;
readonly ICancelWork _cancelWork;
public AbortIfCancelled(IMessageContext messageContext, ICancelWork cancelWork)
{
_messageContext = messageContext;
_cancelWork = cancelWork;
}
public async Task Handle(Work work)
{
if (await _cancelWork.WasCancelled(work))
{
_messageContet.AbortDispatch();
}
}
}
如果ICancelWork
返回true,则终止管道的其余部分。然后,您将不得不实现ICancelWork
,例如,通过将bool填充到数据库的某个地方。
PS: IMessageContext
上的AbortDispatch()
函数可从0.98.11