【问题标题】:Why isn't Task.Delay working in an Azure Function App?为什么 Task.Delay 不能在 Azure Function App 中工作?
【发布时间】:2021-10-13 23:54:22
【问题描述】:

我有一个 C# 函数应用程序 (.net Core 3.1),用于处理队列中的项目。我需要放慢处理速度,因为我需要与另一个外部 API 通信,而且它的速率有限。

我正在使用

await Task.Delay(1000);

在调用 API 之间暂停函数应用一段时间。在我的本地开发环境中,它可以完美运行并在给定的时间段内暂停。部署到 Azure 时,似乎不会出现延迟,并且队列项目的处理速度比预期的要快得多。

我已经用 10000 毫秒(10 秒)的长时间进行了尝试,并且在本地测试时可以看到延迟,但是当部署到 Azure 时,队列项目很快就用完了,而且相隔不到 10 秒。

函数声明如下所示:

[FunctionName("ProcessUserQueue")]
public async Task RunAsync([QueueTrigger(QueueNames.ProcessUserQueueName)]string myQueueItem, ILogger log)
{
    log.LogInformation($"ProcessUserQueue trigger function processed: {myQueueItem}");
    await _userService.ProcessUserAsync(myQueueItem, log);
}

在 ProcessUserAsync 内部,我做的第一件事就是调用

await Task.Delay(10000);

它可以工作,但仅限于本地开发环境。

我的 host.json 看起来像这样(队列批量大小为 1):

{
  "version": "2.0",
  "functionTimeout": "00:10:00",
  "extensions": {
    "queues": {
      "batchSize": 1,
      "maxDequeueCount": 5
    }
  }
}

关于为什么这不起作用,或者如何更好地限制函数内 API 调用的速度的任何想法?

【问题讨论】:

  • 收到消息后,新函数实例可以运行RunAsync。这些实例彼此不知道。
  • 使用Task.Delay 对 API 的请求进行速率限制就像使用勺子试图拯救 泰坦尼克号
  • 彼得,我想你已经明白了。我使用了其中一篇相关帖子,发现了 WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT = 1 的应用程序设置,这应该将应用程序限制为一个实例。这似乎有点帮助,但并不完全。然后我还修改了 host.json 以包含“newBatchThreshold”:0。函数应用程序现在似乎表现得很好。还需要做更多的测试。

标签: c# azure .net-core azure-functions


【解决方案1】:

有多种方法可以延迟进程:

  1. 您可以使用Thread.Sleep(),而不是使用Task.Delay()

    Task.Delay() 用于在不阻塞当前线程的情况下进行逻辑延迟。

    Thread.Sleep()用于阻塞当前线程。

  2. 可以使用durable functions实现进程延时Reference

  3. 它包括设置一个 initialVisibilityDelay : Add message

对于initialVisibilityDelay,您需要添加一个临时队列,然后添加一个函数。

更多请参考info

【讨论】:

    【解决方案2】:

    我不认为在读取队列时向 HttpTrigger 函数添加延迟在实际场景中不起作用,因为如果项目的处理时间超过函数超时期限,该函数将超时。

    对于耗时超过 HttpTrigger 函数超时时间的操作,请使用 Azure Durable Functions

    Durable Functions 提供了持久的计时器,用于编排器函数以实现延迟或设置异步操作的超时。

    [FunctionName("BillingIssuer")]
    public static async Task Run(
        [OrchestrationTrigger] IDurableOrchestrationContext context)
    {
        for (int i = 0; i < 10; i++)
        {
            DateTime deadline = context.CurrentUtcDateTime.Add(TimeSpan.FromDays(1));
            await context.CreateTimer(deadline, CancellationToken.None);
            await context.CallActivityAsync("SendBillingEvent");
        }
    }
    

    有关使用计时器在 Azure Durable 函数中实现延迟,请参阅文章:https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-timers?tabs=csharp

    有关 Azure 持久功能,请参阅:https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-01
      • 2021-03-06
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 2021-10-26
      • 1970-01-01
      • 2021-01-28
      相关资源
      最近更新 更多