Partilhar via


Implementar repetições de chamadas HTTP com backoff exponencial usando IHttpClientFactory e políticas Polly

Sugestão

Este conteúdo é um trecho do eBook, .NET Microservices Architecture for Containerized .NET Applications, disponível no do .NET Docs ou como um PDF para download gratuito que pode ser lido offline.

Miniatura da capa do eBook Arquitetura de Microsserviços .NET para Aplicações .NET Contentorizadas.

A abordagem recomendada para novas tentativas com backoff exponencial é aproveitar bibliotecas .NET mais avançadas, como a biblioteca Polly de código aberto.

Polly é uma biblioteca .NET que fornece resiliência e recursos de tratamento de falhas transitórias. Você pode implementar esses recursos aplicando políticas Polly, como Retry, Circuit Breaker, Bulkhead Isolation, Timeout e Fallback. Polly tem como alvo o .NET Framework 4.x e o .NET Standard 1.0, 1.1 e 2.0 (que oferece suporte ao .NET Core e posterior).

As etapas a seguir mostram como pode usar retries de Http com Polly integrado no IHttpClientFactory, que é explicado na secção anterior.

Instalar pacotes .NET

Primeiro, você precisará instalar o Microsoft.Extensions.Http.Polly pacote.

Fazer referência aos pacotes do .NET 8

IHttpClientFactory está disponível desde o .NET Core 2.1, no entanto, recomendamos que você use os pacotes .NET 8 mais recentes do NuGet em seu projeto. Normalmente, você também precisa fazer referência ao pacote Microsoft.Extensions.Http.Pollyde extensão.

Configurar um cliente com a política de repetição do Polly, na inicialização da aplicação

O método AddPolicyHandler() é o que adiciona políticas aos HttpClient objetos que você usará. Neste caso, é adicionar uma política do Polly para tentativas HTTP com retrocesso exponencial.

Para ter uma abordagem mais modular, a Política de Repetição Http pode ser definida em um método separado dentro do arquivo Program.cs , conforme mostrado no código a seguir:

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

Como mostrado nas seções anteriores, é necessário definir uma configuração HttpClient de cliente nomeada ou especializada na configuração do aplicativo padrão Program.cs. Agora você adiciona código incremental especificando a política para as novas tentativas de Http com backoff exponencial, da seguinte maneira:

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

Com o Polly, você pode definir uma política de repetição com o número de tentativas, a configuração de backoff exponencial e as ações a serem tomadas quando houver uma exceção HTTP, como registrar o erro. Nesse caso, a política é configurada para tentar seis vezes com uma repetição exponencial, começando em dois segundos.

Adicionar uma estratégia de desvio à política de repetição

Uma política de repetição regular pode afetar o seu sistema em casos de alta simultaneidade, alta escalabilidade e sob alta contenção. Para superar picos de tentativas semelhantes provenientes de muitos clientes em interrupções parciais, uma boa solução é adicionar uma estratégia de aleatoriedade ao algoritmo ou política de tentativas. Essa estratégia pode melhorar o desempenho geral do sistema de ponta a ponta. Como recomendado em Polly: Retry with Jitter, uma boa estratégia de jitter pode ser implementada com intervalos de repetição suaves e uniformemente distribuídos, aplicados com um atraso inicial de repetição mediano bem controlado numa estratégia de backoff exponencial. Essa abordagem ajuda a espalhar os picos quando o problema surge. O princípio é ilustrado pelo seguinte exemplo:


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

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

Recursos adicionais