Поделиться через


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

Подсказка

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

Архитектура микросервисов .NET для приложений .NET в контейнерах, миниатюра обложки электронной книги.

Рекомендуемый подход для повторных попыток с экспоненциальным обратным выходом — использовать более сложные библиотеки .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, например ведение журнала ошибки. В этом случае политика настроена на попытку шесть раз с экспоненциальным повтором, начиная с двух секунд.

Добавить стратегию jitter в политику повторных попыток

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


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

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

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