Azure函数的可见性超时

时间:2019-04-19 06:38:36

标签: azure azure-functions azure-storage-queues

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

真相是什么?超时是否仅在功能未运行更多(可能已经失败)时才相关,或者即使功能仍在运行,是否也可能再次显示消息?

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

对此我有点困惑。

2 个答案:

答案 0 :(得分:1)

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

该功能失败时

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

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

这使您的应用程序可以应对瞬态错误。例如,如果电子邮件API或其他外部服务暂时关闭。通过延迟重试,服务可能会重新联机以进行下一次功能尝试。

重试仅限于maxDequeueCount次尝试(默认5次),然后再将邮件移至Poison Queue

函数正在运行

QueueTrigger绑定运行该函数时,它以10分钟的可见性超时(硬编码here)使消息出队。然后,只要功能运行,它将设置一个计时器,以在可见时间达到一半时扩展可见性窗口(请参见源代码中的timervisibility update)。

通常,只要您的函数正确使用CancellationToken,您就不必担心这一点。仅当Azure Function / WebJob主机未到达shut down gracefully时,此10分钟超时才有意义。例如:

因此,只要该功能仍在运行,该消息就将从队列中隐藏起来。

验证

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

[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
...

答案 1 :(得分:0)

我已经用

进行了测试
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. 有关visibleTimeout的文档为true:“消息处理失败时重试之间的时间间隔。 (来自https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue#hostjson-settings

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