Почему это не задача.Задержка работы в приложении функций Azure?

#c# #azure #.net-core #azure-functions

Вопрос:

У меня есть приложение функций 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);
 

и это работает, но только в локальной среде разработки.

Мой хост.json выглядит так (с размером пакета очереди в один):

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

Есть какие-либо идеи относительно того, почему это не работает или как лучше ограничить скорость вызовов API внутри функции?

Комментарии:

1. По прибытии сообщения может быть запущен новый экземпляр функции RunAsync . Эти экземпляры не знают друг о друге.

2. Использование Task.Delay для ограничения скорости запросов к API очень похоже на использование ложки для попытки спасти » Титаник «.

3. Питер, я думаю, ты в курсе. Я использовал один из связанных постов и обнаружил настройку приложения WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT = 1, которая должна ограничивать приложение одним экземпляром. Это, казалось, немного помогло, но не полностью. Затем я также изменил host.json, включив «NewBatchThreshold»: 0. Приложение-функция, похоже, сейчас ведет себя нормально. Еще нужно будет провести еще несколько тестов.

Ответ №1:

Существует несколько способов отсрочить этот процесс:

  1. Вместо использования Task.Delay() вы можете использовать Thread.Sleep() .

    Задача.Функция Delay() используется для логической задержки без блокировки текущего потока.

    Нитки.Функция Sleep() используется для блокировки текущего потока.

  2. Вы можете использовать durable functions для достижения ссылки на задержку процесса
  3. он состоит из установки initialVisibilityDelay : Добавить сообщение

Для initialVisibilityDelay вам нужно добавить временную очередь, а затем добавить функцию.

Обратитесь за дополнительной информацией

Ответ №2:

Я не думаю, что добавление задержки в функцию HttpTrigger при чтении очереди не будет работать в реальном сценарии, так как функция будет отключена, если обработка элементов заняла больше времени, чем время ожидания функции.

Для операций, которые могут занять больше времени, чем время ожидания функции HttpTrigger, используйте надежные функции Azure.

Надежные функции предоставляют надежные таймеры для использования в функциях оркестратора для реализации задержек или настройки тайм-аутов при асинхронных действиях.

 [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 Durable см.: https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp