Реализация повторных попыток вызова HTTP с экспоненциальной задержкой с помощью IHttpClientFactory и политик Polly

Совет

Это содержимое является фрагментом из электронной книги, архитектуры микрослужб .NET для контейнерных приложений .NET, доступных в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно читать в автономном режиме.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Рекомендуемый подход к выполнению повторных попыток с экспоненциальной выдержкой заключается в использовании расширенных библиотек .NET, таких как библиотека Polly с открытым кодом.

Polly — это библиотека .NET, которая предоставляет возможности обеспечения отказоустойчивости и обработки временных сбоев. Эти возможности можно реализовать путем применения политик Polly, таких как политики повтора, размыкателя цепи, изоляции отсеков, времени ожидания и отката. Polly используется с .NET Framework 4.x, а также .NET Standard 1.0, 1.1 и 2.0 (с поддержкой .NET Core и более поздних версий).

Ниже показано, как можно использовать повторные HTTP-запросы через Polly с интеграцией IHttpClientFactory, как описано в предыдущем разделе.

Установка пакетов .NET

Сначала необходимо установить Microsoft.Extensions.Http.Polly пакет.

Ссылка на пакеты .NET 8

IHttpClientFactory доступен с версии .NET Core 2.1, однако мы рекомендуем использовать последние пакеты .NET 8 из NuGet в проекте. Обычно также требуется ссылка на пакет расширения Microsoft.Extensions.Http.Polly.

Настройка клиента с помощью политики повторных попыток Polly в запуске приложения

Метод AddPolicyHandler() добавляет политики для объектов HttpClient, которые вы будете использовать. В этом случае он добавляет политику Polly для повторных HTTP-запросов с экспоненциальной задержкой.

Чтобы обеспечить более модульный подход, политика повторных попыток Http может быть определена в отдельном методе в файле Program.cs , как показано в следующем коде:

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2,
                                                                    retryAttempt)));
}

Как показано в предыдущих разделах, необходимо определить именованную или типизированные конфигурацию клиента HttpClient в стандартной конфигурации приложения Program.cs . Теперь вы добавите добавочный код, указывающий политику для повторных попыток Http с экспоненциальным обратным выходом, как показано ниже.

// Program.cs
builder.Services.AddHttpClient<IBasketService, BasketService>()
        .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Set lifetime to five minutes
        .AddPolicyHandler(GetRetryPolicy());

С помощью Polly вы определяете политику повтора с числом повторных попыток, конфигурацией экспоненциальной задержки и действиями, которые необходимо выполнить в случае исключения HTTP (например, запись ошибки в журнал). В этом случае политика настроена на шесть попыток с экспоненциальной выдержкой, начиная с двух секунд.

Добавление стратегии обработки колебания задержки в политику повтора

Обычная политика повтора может влиять на работу системы в случае высокого уровня параллелизма и масштабируемости, а также в условиях интенсивного состязания за ресурсы. Чтобы решить проблему с большим числом повторных запросов, поступающих от множества клиентов при частичном отказе системы, можно добавить стратегию в отношении колебания задержки в алгоритм или политику повтора. Эта стратегия может повысить общую производительность всей системы. Как рекомендуется в статье Polly: повторы с колебаниями задержки, хорошая стратегия должна предусматривать плавный и равномерно распределенный интервал повторов, который применяется с контролируемой средней исходной задержкой повторов на базе экспоненциальной задержки. Такой подход способствует размытию пиков при возникновении проблем. Этот принцип проиллюстрирован в следующем примере.


var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5);

var retryPolicy = Policy
    .Handle<FooException>()
    .WaitAndRetryAsync(delay);

Дополнительные ресурсы