首页 > 解决方案 > 为什么 Task.Delay 不能在 Azure Function App 中工作?

问题描述

我有一个处理队列中的项目的 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 调用的速度的任何想法?

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

解决方案


我不认为在读取队列时向 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


推荐阅读