Azure 函数可见性超时



当我阅读有关可见性超时的文档时:https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue#host-json 它说"处理消息失败时重试之间的时间间隔。我的理解是,如果超时设置为 30 秒并且我的函数运行了 1 分钟,但在这 1 分钟内没有失败,则该消息对队列中的其他人不可见。但是当我通过其他来源(stackoverflow fx)阅读它时,它告诉我相反的情况,当函数的执行时间超过超时时,即使函数仍在处理消息,消息也会变得可见。

真相是什么?超时是否仅在函数未运行更多(并且可能已失败)时才相关,或者即使函数仍在运行,消息也会再次可见?

如果我们假设消息在达到超时时可见,那么默认超时为 00:00:00,这意味着消息在取消排队的同时可见,这也没有意义。这与什么相矛盾 3.党内消息人士说。

我对此有点困惑。

这里似乎使用了两个不同的可见性超时值。两者都由 Azure WebJobs SDK 设置,但只有一个是可配置的。

当函数失败时

queues.visibilityTimeout配置选项将更恰当地命名为retryDelay

当函数引发异常或因某种其他类型的错误而失败时,消息将返回到队列以重试。该消息随配置的visibilityTimeout一起返回(请参阅此处),这会延迟函数下次尝试运行的时间。

这使您的应用程序能够处理暂时性错误。例如,如果电子邮件 API 或其他外部服务暂时关闭。通过延迟重试,服务可能会在下一次函数尝试中重新联机。

重试次数限制为maxDequeueCount次尝试(默认为 5 次),然后邮件才会移动到病毒队列。

函数运行时

QueueTrigger绑定运行函数时,它会以 10 分钟的可见性超时取消消息的排队(此处硬编码)。然后,只要函数正在运行,它就会设置一个计时器,以便在达到半场时延长可见性窗口(请参阅源中的计时器和可见性更新)。

通常,只要您的函数正确使用CancellationToken,您就无需担心这一点。仅当 Azure 函数/Web 作业主机无法正常关闭时,此 10 分钟超时才重要。例如:

  • 有人在网络主机上"拔掉插头">
  • 如果函数在缩减或其他 Azure 关闭事件期间未及时响应CancellationToken

因此,只要函数仍在运行,消息就会在队列中保持隐藏状态。

验证

我做了一个类似的实验来检查:

[FunctionName("SlowJob")]
public async Task Run(
[QueueTrigger("slow-job-queue")] CloudQueueMessage message,
ILogger log)
{
for (var i = 0; i < 20; i++)
{
log.LogInformation($"Next visible {i}: {message.NextVisibleTime}");
await Task.Delay(60000);
}
}

输出:

Next visible 0: 5/11/2020 7:49:24 +00:00
Next visible 1: 5/11/2020 7:49:24 +00:00
Next visible 2: 5/11/2020 7:49:24 +00:00
Next visible 3: 5/11/2020 7:49:24 +00:00
Next visible 4: 5/11/2020 7:49:24 +00:00
Next visible 5: 5/11/2020 7:54:24 +00:00
Next visible 6: 5/11/2020 7:54:24 +00:00
Next visible 7: 5/11/2020 7:54:24 +00:00
Next visible 8: 5/11/2020 7:54:24 +00:00
Next visible 9: 5/11/2020 7:54:24 +00:00
Next visible 10: 5/11/2020 7:59:24 +00:00
Next visible 11: 5/11/2020 7:59:24 +00:00
...

我已经用

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Queue;
namespace WorkerFunctions
{
public static class WorkerFunctions
{
[FunctionName("WorkerFunction1")]
public static async Task Function1(
[QueueTrigger("outputQueue")]
CloudQueueMessage item,
[Queue("outputQueue")]
CloudQueue outputQueue,
DateTimeOffset nextVisibleTime,
DateTimeOffset expirationTime,
DateTimeOffset insertionTime,
ILogger log)
{
log.LogInformation("########## Function 1 ###############");
log.LogInformation($"NextVisibleTime: {nextVisibleTime}");
log.LogInformation($"NextVisibleTime: {(nextVisibleTime-insertionTime).TotalSeconds}");
log.LogInformation($"C# Queue trigger function processed: {item.AsString}");
Thread.Sleep(TimeSpan.FromMinutes(20));
}
[FunctionName("WorkerFunction2")]
public static async Task Function2(
[QueueTrigger("outputQueue")]
CloudQueueMessage item,
[Queue("outputQueue")]
CloudQueue outputQueue,
DateTimeOffset nextVisibleTime,
DateTimeOffset expirationTime,
DateTimeOffset insertionTime,
ILogger log)
{
log.LogInformation("########## Function 2 ###############");
log.LogInformation($"NextVisibleTime: {nextVisibleTime}");
log.LogInformation($"NextVisibleTime: {(nextVisibleTime - insertionTime).TotalSeconds}");
log.LogInformation($"C# Queue trigger function processed: {item.AsString}");
Thread.Sleep(TimeSpan.FromMinutes(20));
}
}
}

使用此主机文件

{
"version": "2.0",
"extensions": {
"queues": {
"maxPollingInterval": "00:00:02",
"visibilityTimeout": "00:00:10",
"batchSize": 16,
"maxDequeueCount": 5,
"newBatchThreshold": 8
}
}
}

当我将一条简单的消息放在队列中并让它运行时,我看到以下内容:

  1. 抓住它的功能,在睡眠结束之前不会释放它
  2. 我在日志中看不到租约已续订,但似乎它发生在引擎盖下

这告诉我什么:

如果函数没有失败,
  1. 或者主机没有失败,那么租约将根据以下条件自动续订: https://stackoverflow.com/a/31883806/21199
  2. 当达到可见性超时并且函数正在运行时,消息不会"重新添加"到队列中
  3. 有关可见性超时的文档为真:"处理消息失败时重试之间的时间间隔。(来自 https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue#hostjson-settings)

我没有保存任何与此相矛盾的 3. 派对的链接(对不起,我没有保存这些),但它们存在。我希望有人能回答这个问题,这样我就可以得到澄清。

最新更新