我有一个功能:
public async static Task Run([QueueTrigger("efs-api-call-last-datetime", Connection = "StorageConnectionString")]DateTime queueItem,
[Queue("efs-api-call-last-datetime", Connection = "StorageConnectionString")]CloudQueue inputQueue,
TraceWriter log)
{
然后我需要很长的时间来处理队列中的消息。问题是在我处理此消息的30秒后,该消息将被读入队列。我不需要添加此消息并对其进行两次处理。 我想要类似的代码:
try
{
// long operation
}
catch(Exception ex)
{
// something wrong. Readd this message in 1 minute
await inputQueue.AddMessageAsync(new CloudQueueMessage(
JsonConvert.SerializeObject(queueItem)),
timeToLive: null,
initialVisibilityDelay: TimeSpan.FromMinutes(1),
options: null,
operationContext: null
);
}
,并防止自动读取。有办法吗?
答案 0 :(得分:2)
这里有几件事。
1)当有多个队列消息在等待时,队列触发器将检索一批消息并同时调用函数实例以对其进行处理。默认情况下,批处理大小为16。但这可以在Host.json中配置。如果要最小化并行执行,可以将批处理大小设置为1。 Microsoft document对此进行了解释。
2)由于它是一个运行时间很长的过程,因此您的消息似乎不完整,并且该函数可能超时并且消息再次可见。您应该尝试将功能分解为较小的功能。然后,您可以使用持久功能,将需要完成的工作链接在一起。
答案 1 :(得分:1)
是的,您可以使同一条消息出队两次。
原因:
1.Worker A使消息B出队,并且可见超时到期。消息B再次变为可见,并且工作程序C使消息B出队,使工作程序A的回执无效。工人A完成工作,删除消息B,并引发错误。这是最常见的。
2。触发第一个Azure函数执行的原始消息上的锁定可能即将到期。这将导致Queue假定处理消息失败,然后将使用该消息来触发Function再次执行。
3。在某些情况下(非常频繁的队列轮询),您可以在GetMessage
上两次收到相同的消息。这是一种竞赛情况,尽管确实很少发生。工人A和B的轮询速度非常快,并且同时进入队列,并且都收到相同的消息。在高轮询情况下,这种情况过去更为普遍(SDK 1.0时间范围),但现在在以后的存储更新中变得越来越罕见(不记得最近看到过这种情况)。
1和3仅在您有1个以上的工人时发生。
解决方法:
安装azure-webjobs-sdk
1.0.11015.0版本(在“功能”门户的“设置”页面中可见)。有关更多详细信息,您可以参考fixing queue visibility renewals