我目前正在使用WebJobs SDK来使用队列中发出的消息。
我的方法作为一个参数与[Microsoft.Azure.WebJobs.QueueTrigger(...)]属性一起被触发好了。 在某些情况下,该方法可以处理消息,但有时,我希望它拒绝消息,直到关键资源可用。
我试图在这种情况下抛出异常,但与引用所说的相反,队列触发器会立即再次触发(显然没有等待租用时间)。
有没有办法优雅地推迟邮件处理? 冻结线程等待关键资源是否安全?
任何提示都会非常感激。
答案 0 :(得分:1)
我认为您不能在当前版本中推迟发送消息。
可能的解决方法
您可以延迟重新添加相同的邮件,为避免重复,您可以将MaxDequeueCount
设置为1
,这会将失败的邮件直接发送到异常后的队列队列:
JobHostConfiguration configuration = new JobHostConfiguration();
configuration.Queues.MaxDequeueCount = 1;
和消息处理器 - 重新添加延迟消息并抛出异常:
public static void ProcessMessage([QueueTrigger("resource-heavy-queue")] string message, [Queue("resource-heavy-queue")] CloudQueue originalQueue)
{
if ( /*Resource unavaliable*/)
{
var messageToReAdd = new CloudQueueMessage(message);
originalQueue.AddMessage(messageToReAdd, null, TimeSpan.FromSeconds(10));
throw new ResourcesNotAvailableException();
}
}
这样您就可以为您的资源实施某种退避策略。不幸的是,你必须手动处理一些问题:
NumberOfRetries
并在每次重新添加时将其递增< / LI>
Id
和InsertionTime
会有所不同,因此您无法依赖它们。答案 1 :(得分:0)
抱歉,无法推迟触发器。你想要的是Azure WebJobs SDK没有的多重触发器(当消息和资源可用时触发)
有一些解决方法。如果该队列中的所有消息需要关键资源,您可以冻结该线程 - 您正在实现信号量 - 否则,调度变得棘手,因为如果达到最大数量,SDK将不会处理新消息并行运行的函数。
我会做什么而不是触发队列消息是关键资源上的触发器。当资源可用时,它会将消息放入另一个队列中,然后检查是否有任何要处理的消息需要该资源。
答案 2 :(得分:0)
我在这种情况下所做的是为同一个队列设置一个public static async Task HandleMessagesAsync([ServiceBusTrigger("%QueueName%")] BrokeredMessage message, [ServiceBus("%QueueName%")]ICollector<BrokeredMessage> queue, TextWriter logger)
我是从
%QueueName%
(if (needToWait)
{
var delayedMessage = new BrokeredMessage(originalMessageBody) { Label = originalLabel, MessageId = originalMessageId, ScheduledEnqueueTimeUtc = DateTime.UtcNow + this.ExecutionDelay };
queue.Add(delayedMessage);
return;
}
表示法使SDK从app.config获取值
然后在处理程序中我正在做类似
的事情{{1}}
这样当前消息就完成了,但是在定义的超时后,计划发送一个具有相同属性的新消息。
制作此程序时没有阻止任何线程。