У меня есть функция Azure HTTP-триггера, которая добавляет сообщение в очередь: outputQueue.AddAsync (myMessage); Затем запускается функция Azure, запускающая очередь. Он добавляет 100 сообщений в одну очередь. Каждое из этих 100 сообщений удаляется этой функцией и обрабатывается. Эта обработка занимает около 5-7 минут. Моя функция Timeout составляет 10 минут. Иногда (в 10% вызовов) одно и то же сообщение удаляется из очереди и обрабатывается дважды и даже больше, хотя предыдущая обработка этого сообщения была успешной. Также я обратил внимание на то, что каждая такая избыточная очередь происходит примерно через 10 минут после предыдущей очереди того же самого массажа (кажется, это связано с моей функцией Timeout 10 минут). Таким образом, похоже, что после завершения обработки функция не завершается и, следовательно, не удаляется из очереди, что приводит к тому, что другой экземпляр удаляет ее из очереди.
Когда я смотрю на раздел «Сбои» в Application Insights, я вижу, что примерно для операций с 1 КБ у меня есть около 10 исключений WebExceptions и 2 TimeoutExceptions.
WebException:
Сообщение: удаленный сервер возвратил ошибку: (409) Конфликт.
Неудачный метод:
Microsoft.WindowsAzure.Storage.Shared.Protocol.HttpResponseParsers.ProcessExpectedStatusCodeNoExceptiond
FormattedMessage: произошло необработанное исключение. Хост закрывается.
TimeoutException:
Сообщение: клиент не смог завершить операцию в течение указанного времени ожидания. Клиент не смог завершить операцию в течение указанного времени ожидания.
Сбой метода: Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndExecuteAsync
FormattedMessage: произошло необработанное исключение. Хост закрывается.
У меня есть try..catch в моей точке входа в функцию, но, вероятно, эти 2 исключения не идут в блок catch.
Мой host.json выглядит следующим образом:
{
"functionTimeout": "00:10:00",
"version": "2.0",
"extensions": {
"queues": {
"maxPollingInterval": 1000,
"visibilityTimeout": "01:00:00",
"batchSize": 8,
"maxDequeueCount": 5,
"newBatchThreshold": 4
}
}
}
Когда я устанавливаю «batchSize»: 2 и «newBatchThreshold»: 1 у меня меньше избыточных очередей, но создается больше экземпляров (я знаю это, регистрируя IP-адрес сервера каждого вызова функции Azure). Если у меня больше серверов, которые обрабатывают разные сообщения, тогда мои статические данные реже используются между экземплярами.
Также обратите внимание, что я установил «visibilityTimeout» на 1 час (я тоже пробовал 30 минут), но похоже, что это значение полностью игнорируется, и сообщение становится видимым через 10 минут.
Есть идеи, как избежать дублирования в обработке одних и тех же сообщений? Я подумываю о том, чтобы записать информацию о сообщении в БД после успешной обработки и при каждой очереди сообщения проверять, было ли обработано это сообщение, скажем, в течение 1 часа и, если да, не обрабатывать его снова. Еще одна опция, о которой я думаю, - установить для параметра maxDequeueCount значение 1 (у меня есть механизм восстановления, если некоторые сообщения вообще не будут обрабатываться из-за какого-либо реального сбоя).
Кстати, эти 10% избыточных обработок не вызывают проблем с функциональностью, но я все еще хочу улучшить производительность.