我们通过NServiceBus使用Azure服务总线,因为消息导致处理长时间运行的任务时遇到了问题。
正如良好的做法一样,我们不希望阻止消息处理程序返回,使其等待长时间运行的进程(从远程服务器下载大文件),实际上这样做会导致对消息的锁定与Azure SB一起迷失。计划是通过生成单独的任务来响应,并允许消息处理程序立即返回。
但是,这意味着处理程序现在可以立即用于下一条消息,这将导致生成另一个任务,依此类推,直到消息队列为空。我想要的是在我们处理(有限数量)早期消息时停止接收消息的某种方式。 NServiceBus和Azure Service Bus是否有可接受的模式?
如果我直接针对Azure SB进行编程,以下是我要做的事情
{
while(true)
{
var message = bus.Next();
message.Complete();
// Do long running stuff here
}
}
动词Next和Complete可能是错误的,但在Azure下发生的事情是Next会对消息进行临时锁定,以便其他消费者无法再看到该消息。然后,您可以决定是否确实要处理该消息,如果是,则调用完成。然后,这将完全从队列中删除消息,否则将导致消息在一段时间后显示回队列,因为Azure假定您已崩溃。像这段代码一样脏,它会实现我的目标(所以为什么不这样做呢?)因为我的消费者只会在下次我可用时消耗(在长时间运行的任务之后)。其他消费者(其他情况)可以在必要时加入。
问题是NServiceBus添加了一个抽象级别,因此现在处理消息是通过处理程序类上的方法。
void Handle(NewFileMessage message)
{
// Do work here
}
问题是Azure在您的工作之后和Handle方法退出之后才会调用message.Complete()。这就是为什么你需要保持工作的简短。但是,如果您退出,则还表示您已准备好处理另一条消息。这是我的Catch 22
答案 0 :(得分:2)
在后台线程上下载是个好主意。你不想增加锁定持续时间,因为这是一个症状,而不是问题。您的下载很容易超过最长锁定时间(5分钟),然后您又回到原点。
你可以做的是有一个编排的传奇下载。 Saga可以监控下载过程,当下载完成后,b / g进程会向saga发出关于完成的信号。如果从未完成下载,您可以暂停(或多次超时)以指示并进行补偿操作或重试,无论哪种方式适用于您的业务案例。
有关Sagas的文档可以帮助您:http://docs.particular.net/nservicebus/sagas/
答案 1 :(得分:0)
在Azure Service Bus中,您可以增加邮件的锁定持续时间(默认设置为30秒),以防处理需要很长时间。
但是,除了你能够增加你的锁定持续时间之外,它通常表明你的处理程序需要处理很多可以通过不同处理程序进行划分的工作。
答案 2 :(得分:0)
如果下载文件至关重要,我会将下载操作保留在处理程序中。这样,如果下载失败,则可以再次处理该消息并且可以重试下载。但是,如果您想立即释放处理程序以处理更多消息,我建议您扩展执行下载任务的工作人员,以便系统能够应对需求。