HttpClientFactory no .NET 8
Published: 2023-12-22 10:59:09

Reaproveitamento dos _pools_ de conexões, reduzindo o consumo de recursos do socket, este é o resumo da utilização do _HttpClientFactory_ no .NET.

## Introdução
Não saber utilizar corretamente o _HttpClient_ no .NET é um erro clássico, como criar várias instâncias no projeto, isso causa um acúmulo de utilização de sockets, aumentando o consumo de processamento e o famoso _memory leak_.

A criação de uma instância _HttpClient_ cria internamente uma cadeia _HttpMessageHandler_, que é responsável por estabelecer uma conexão. Portanto, quando descartamos o _HttpClient_, na verdade descartamos o _HttpMessageHandler_, que acabará fechando a conexão. O risco é que a conexão não seja fechada assim que o cliente for descartado.

 ![HttpMessageHandler](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukzye6s5va3oh8sssyus.png)

Uma solução para o problema acima era ter uma única instância de um _HttpClient_ que seria compartilhada em toda aplicação.

Mas, o problema em utilizar uma única instância na solução é que as conexões seriam mantidas abertas e reutilizadas para sempre e quaisquer alterações de DNS feitas nos serviços remotos não seriam respeitadas.

Isso faria com que a aplicação apontassem para instâncias de servidor offline ou ambientes incorretos.

## Apresentando a HttpClientFactory
- O HttpClientFactory foi introduzido com .NETCore 2.1.
- O HttpClientFactory nos dá um local central para configurar e criar HttpClients.
- Ele gerencia o tempo de vida das cadeias _HttpMessageHandler_ subjacentes. Ele faz isso gerenciando um pool desses _MessageHandlers_ e mantendo-os abertos até que expirem.
- Os _MessageHandlers_ são mantidos ativos por no máximo 2 minutos.
- O uso é simples e requer mudanças mínimas de código em sua aplicação.
- Apenas chamar o método de extensão _AddHttpClient_ no _IServiceCollection_ oferece as vantagens do gerenciamento de instâncias pronto para uso.
- Ele permite que você injete o _HttpClientFactory_ em qualquer lugar da sua aplicação.

## Exemplo de utilização do HttpClientFactory

O código abaixo é um exemplo de utilização do _HttpClientFactory_ com o _Polly_, onde trabalharemos a resiliência.

```csharp
public static class HttpClientCollectionEExtension
    {
        public static void ConfigureHttpClientService(this IServiceCollection services, IConfiguration configuration)
        {
            var retryPolicy = Policy
                .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode && r.StatusCode != HttpStatusCode.BadRequest)
                .WaitAndRetryAsync(new[]
                {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(3),
                    TimeSpan.FromSeconds(6)
                });

            services.AddHttpClient("taxa", c =>
            {
                c.BaseAddress = new Uri($"{configuration.GetSection("UrlApiTaxa").Value}");

                c.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
                c.DefaultRequestHeaders.Add("Keep-Alive", "3600");
                c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");

            }).AddPolicyHandler(retryPolicy);
        }
    }
```

Depois de ser registrado em seu _startup.cs_, agora precisamos consumir este _HttpClient_, conforme o código de exemplo abaixo:

```csharp
public class TaxaJurosExternalClient : ITaxaJurosExternalClient
    {
        public readonly IHttpClientFactory _factory;

        public TaxaJurosExternalClient(IHttpClientFactory factory)
        {
            _factory = factory;
        }

        public async Task<double> GetTaxaJuros()
        {
            var client = _factory.CreateClient("taxa");

            var result = await client.GetAsync("Get");

            var resultContent = await result.Content.ReadAsStringAsync();

            var resultObject = JsonSerializer.Deserialize<TaxaJurosOutput>(resultContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

            return resultObject.Taxa;

        }
    }
```

Repare que nenhuma instância do _HttpClient_ foi criado, simplesmente é reutilizado da nossa configuração no _startup.cs_, o que deixa seu código muito mais performático e organizado.

O exemplo completo de utilização do _HttpClientFactory_ com o _Polly_, você confere no link abaixo:

https://github.com/hgmauri/sample-httpclientfactory-polly