ASP.NET Core 3.0 + Polly: simplificando o tratamento de falhas em projetos Web
Já abordei o uso da biblioteca Polly com .NET Core em um artigo de Agosto/2019, no qual demonstrei como efetuar o tratamento de tokens expirados ao consumir uma API REST protegida por JWT:
.NET Core + Polly + JWT: tratando de forma resiliente a expiração de tokens
Neste novo post apresento um exemplo de utilização de Polly com ASP.NET Core 3.0, desta vez integrando este framework a um Typed Client criado para consumo de uma API REST. Para saber mais a respeito da implementação de Typed Clients acesse os links a seguir:
ASP.NET Core 2.1: utilizando HTTPClient Factory
ASP.NET Core: boas práticas na implementação de APIs REST - Outubro-2019
Aproveito este espaço para deixar aqui também um convite. Entre os dias 2 e 4 de Dezembro/2019 acontecerá o DevWeek 2019, o evento de final de ano do Canal .NET voltado a desenvolvedores de software.
Serão 9 palestras noturnas, gratuitas e online ao longo de 3 dias, cobrindo diversas tecnologias e temas de destaque na área de software (sobretudo .NET e Microsoft Azure).
Para efetuar sua inscrição acesse este link e faça sua inscrição pelo Meetup, a transmissão será via YouTube e a grade será divulgada em breve.
Implementando o uso de Polly em ASP.NET Core 3.0
O projeto apresentado neste post (SiteConsumoAPIContagem) já foi disponibilizado no GitHub:
https://github.com/renatogroffe/ASPNETCore3.0_WebApp_Polly
Diferentemente do que aconteceu no artigo sobre .NET Core + Polly indicado anteriormente, será adicionado ao projeto SiteConsumoAPIContagem o package Microsoft.Extensions.Http.Polly (a biblioteca Polly já virá como uma dependência deste pacote):
Na classe LogFileHelper foi definido o método estático WriteMessage:
- Esta operação fará uso do método AppendAllText da classe File (namespace System.IO), gravando mensagens que permitirão entender melhor o fluxo de tratamento de falhas com Polly;
- Tais mensagens serão registradas em um arquivo chamado log-polly.txt, este último gerado no mesmo diretório em que se encontra a aplicação.
A classe APIContagemClient será utilizada como um Typed Client:
- Esse tipo receberá como parâmetro em seu construtor uma instância de HttpClient (namespace System.Net.Http), empregando a mesma no envio de requisições HTTP à API que consumiremos. Também estão sendo repassados ao construtor como parâmetros objetos baseados nos tipos IConfiguration e ILogger;
- O método ObterDadosContagem enviará requisições à API REST, devolvendo o resultado da mesma como uma string JSON. É importante destacar aqui a ausência de qualquer trecho prevendo exceções; ao configurar o uso de Polly na classe Startup implementaremos o tratamento de falhas;
- A operação WriteMessage de LogFileHelper será acionada na linha 39, gravando no arquivo log-polly.txt o resultado devolvido pela API REST de testes.
No item UrlAPIContagem do arquivo appsettings.json está a URL da API REST a ser consumida pela classe APIContagemClient:
Trata-se da API de contagem de acessos, um projeto que venho utilizando em diversas demonstrações e que já conta com uma versão em ASP.NET Core 3.0 no GitHub:
https://github.com/renatogroffe/ASPNETCore3.0_Docker
Alterei propositalmente este projeto de forma que falhe quando o contador de acessos for um número múltiplo de 3. Com isto conseguirei testar falhas, verificando o comportamento da aplicação ao se configurar a utilização da biblioteca Polly.
No método ConfigureServices da classe Startup estão as configurações para uso do Typed Client APIContagemClient e da biblioteca Polly:
- Na linha 24 foi especificado o uso de uma Policy baseada no padrão Retry (a biblioteca possibilita ainda a utilização de outros patterns como Timeout e Circuit Breaker). Através do método HandleResult foi indicada a condição de falha, um código HTTP de retorno inválido vinculado a um objeto do tipo HttpResponseMessage. Já em RetryAsync está o tratamento, neste caso uma mensagem indicando uma retentativa em curso;
- Uma chamada ao método AddHttpClient de IServiceCollection (linha 33) permitirá que o Typed Client APIContagemClient seja obtido via injeção de dependência em outros pontos da aplicação. Ao invocar a operação AddPolicyHandler e repassar a Policy criada no passo anterior determinamos assim o tratamento de falhas para instâncias de APIContagemClient; qualquer exceção ocorrida no método ObterDadosContagem acionará o conjunto de instruções indicado em RetryAsync, com um máximo de 2 retentativas.
A aplicação aqui detalhada fará uso de Razor Pages. Na próxima listagem temos o conteúdo do arquivo Index.cshtml.cs, com uma instância de APIContagemClient sendo obtida via injeção de dependência no método OnGet. Na sequência o método ObterDadosContagem foi acionado, com o objeto TempData recebendo o retorno desta operação:
O resultado devolvido pela API de contagem será exibido através do arquivo Index.cshtml:
Testes
Na imagem a seguir podemos observar o projeto SiteConsumoAPIContagem em execução, sendo 7 o valor atual do contador de acessos da API de testes:
Ao analisar o conteúdo do arquivo log-polly.txt notamos que as chamadas para os valores 3 e 6 geraram erros, o que levou a aplicação a retentativas que tiveram sucesso (valores 4 e 7):