Compartilhar via


Introdução ao desenvolvimento resiliente de aplicativos

Resiliência é a capacidade de um aplicativo se recuperar de falhas transitórias e continuar funcionando. No contexto da programação do .NET, a resiliência é obtida com a criação de aplicativos que podem lidar com falhas normalmente e se recuperar rapidamente. Para ajudar a criar aplicativos resilientes no .NET, os dois pacotes a seguir estão disponíveis no NuGet:

Pacote NuGet Descrição
📦 Microsoft.Extensions.Resilience Esse pacote NuGet fornece mecanismos para proteger aplicativos contra falhas transitórias.
📦 Microsoft.Extensions.Http.Resilience Esse pacote NuGet fornece mecanismos de resiliência especificamente para a HttpClient classe.

Esses dois pacotes NuGet são criados com base no Polly, que é um projeto popular de software livre. Polly é uma biblioteca de resiliência e manipulação de falhas transitórias do .NET que permite que aos desenvolvedores expressarem as estratégias como repetição, circuit breaker, tempo limite, isolamento bulkhead, limitação de taxa, fallback e hedging de forma mais fluente e thread-safe.

Importante

O pacote NuGet Microsoft.Extensions.Http.Polly foi preterido. Em vez disso, use um dos pacotes mencionados acima.

Comece agora

Para começar a usar a resiliência no .NET, instale o pacote NuGet Microsoft.Extensions.Resilience .

dotnet add package Microsoft.Extensions.Resilience --version 8.0.0

Para obter mais informações, consulte dotnet package add ou Gerenciar dependências de pacotes em aplicativos .NET.

Criar um pipeline de resiliência

Para usar a resiliência, primeiro você deve criar um pipeline de estratégias baseadas em resiliência. Cada estratégia configurada é executada em ordem de configuração. Em outras palavras, a ordem é importante. O ponto de entrada é um método de extensão do tipo IServiceCollection, denominado AddResiliencePipeline. Esse método usa um identificador do pipeline e um delegado que configura o pipeline. O delegado recebe uma instância ResiliencePipelineBuilder, que é usada com o objetivo de adicionar estratégias de resiliência ao pipeline.

Considere o seguinte exemplo de cadeia de caracteres baseado em key:

using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Registry;
using Polly.Retry;
using Polly.Timeout;

var services = new ServiceCollection();

const string key = "Retry-Timeout";

services.AddResiliencePipeline(key, static builder =>
{
    // See: https://www.pollydocs.org/strategies/retry.html
    builder.AddRetry(new RetryStrategyOptions
    {
        ShouldHandle = new PredicateBuilder().Handle<TimeoutRejectedException>()
    });

    // See: https://www.pollydocs.org/strategies/timeout.html
    builder.AddTimeout(TimeSpan.FromSeconds(1.5));
});

O código anterior:

  • Cria uma nova instância de ServiceCollection.
  • Define key para identificar o pipeline.
  • Adiciona um pipeline de resiliência à instância ServiceCollection.
  • Configura o pipeline com estratégias de repetição e tempo limite.

Cada pipeline é configurado para um determinado key, e cada key é usado para identificar seu respectivo ResiliencePipeline correspondente ao obter o pipeline do provedor. É key um parâmetro de tipo genérico do AddResiliencePipeline método.

Extensões do construtor de pipeline de resiliência

Para adicionar uma estratégia ao pipeline, chame qualquer um dos métodos de extensão Add* disponíveis na instância ResiliencePipelineBuilder.

  • AddRetry: tente novamente se algo falhar, o que é útil quando o problema é temporário e pode desaparecer.
  • AddCircuitBreaker: pare de tentar se algo está quebrado ou ocupado, o que beneficia você evitando o tempo perdido e piorando as coisas.
  • AddTimeout: desista se algo demorar muito, para melhorar o desempenho ao liberar recursos.
  • AddRateLimiter: limite quantas solicitações você aceita, o que permite controlar a carga de entrada.
  • AddConcurrencyLimiter: limite quantas solicitações você faz, o que permite controlar a carga de saída.
  • AddFallback: faça outra coisa ao sofrer falhas, o que melhora a experiência do usuário.
  • AddHedging: emita várias solicitações em caso de alta latência ou falha, o que pode melhorar a capacidade de resposta.

Para obter mais informações, consulte estratégias de resiliência. Para obter exemplos, consulte Criar aplicativos HTTP resilientes: principais padrões de desenvolvimento.

Enriquecimento de métricas

Enriquecimento é o acréscimo automático da telemetria com o estado bem-conhecido, na forma de pares nome/valor. Por exemplo, um aplicativo pode emitir um log que inclui a operação e o código de resultado como colunas para representar o resultado de alguma operação. Nessa situação e dependendo do contexto periférico, o enriquecimento adiciona o nome do cluster, o nome do processo, a região, a ID do locatário e muito mais ao log conforme ele é enviado para o back-end de telemetria. Quando o enriquecimento é adicionado, o código do aplicativo não precisa fazer nada extra para se beneficiar de métricas enriquecidas.

Como funciona o enriquecimento

Imagine 1.000 instâncias de serviço distribuídas globalmente gerando logs e métricas. Quando você encontra um problema no painel de serviço, é crucial identificar rapidamente a região problemática ou o data center. O enriquecimento garante que os registros de métrica contenham as informações necessárias para identificar falhas em sistemas distribuídos. Sem enriquecimento, a carga recai sobre o código do aplicativo para gerenciar internamente esse estado, integrá-lo ao processo de registro em log e transmiti-lo manualmente. O enriquecimento simplifica esse processo, tratando-o perfeitamente sem afetar a lógica do aplicativo.

No caso de resiliência, quando você adiciona enriquecimento, as seguintes dimensões são adicionadas à telemetria de saída:

  • error.type: versão de baixa cardinalidade das informações de uma exceção.
  • request.name: o nome da solicitação.
  • request.dependency.name: o nome da propriedade de dependência.

Nos bastidores, o enriquecimento da resiliência é criado de acordo com a Telemetria MeteringEnricher de Polly. Para obter mais informações, consulte Polly: enriquecimento da medição.

Adicionar enriquecimento de resiliência

Além de registrar um pipeline de resiliência, você também pode registrar o enriquecimento de resiliência. Para adicionar enriquecimento, chame o AddResilienceEnricher(IServiceCollection) método de extensões na IServiceCollection instância.

services.AddResilienceEnricher();

Ao chamar o método de extensão AddResilienceEnricher, você está adicionando dimensões além das que são padrão e incorporadas à biblioteca Polly subjacente. As seguintes dimensões de enriquecimento são adicionadas:

Usar o pipeline de resiliência

Para usar um pipeline de resiliência configurado, você deve obter o pipeline de ResiliencePipelineProvider<TKey>. Quando você adicionou o pipeline anteriormente, key era do tipo string; portanto, você deve obter o pipeline direto de ResiliencePipelineProvider<string>.

using ServiceProvider provider = services.BuildServiceProvider();

ResiliencePipelineProvider<string> pipelineProvider =
    provider.GetRequiredService<ResiliencePipelineProvider<string>>();

ResiliencePipeline pipeline = pipelineProvider.GetPipeline(key);

O código anterior:

  • Cria uma instância ServiceProvider a partir de ServiceCollection.
  • Obtém ResiliencePipelineProvider<string> do provedor de serviços.
  • Recupera o ResiliencePipeline de ResiliencePipelineProvider<string>.

Executar o pipeline de resiliência

Para usar o pipeline de resiliência, chame qualquer um dos métodos Execute* disponíveis na instância ResiliencePipeline. Por exemplo, considere um exemplo de chamada ao ExecuteAsync método:

await pipeline.ExecuteAsync(static cancellationToken =>
{
    // Code that could potentially fail.

    return ValueTask.CompletedTask;
});

O código anterior executa o delegado dentro do ExecuteAsync método. Quando há falhas, as estratégias configuradas são executadas. Por exemplo, se RetryStrategy estiver configurado para tentar novamente três vezes, o delegado será executado quatro vezes (uma tentativa inicial mais três tentativas de repetição) antes que a falha seja propagada.

Próximas etapas