Diretrizes para usar o HttpClient
A classe System.Net.Http.HttpClient envia solicitações HTTP e recebe respostas HTTP de um recurso identificado por um URI. Uma instância HttpClient é uma coleção de configurações aplicadas a todas as solicitações executadas por essa instância e cada instância usa seu próprio pool de conexões, o que isola suas solicitações de outras. A partir do .NET Core 2.1, a classe SocketsHttpHandler fornece a implementação, tornando o comportamento consistente em todas as plataformas.
Comportamento DNS
HttpClient só resolve entradas DNS quando uma conexão é criada. Ele não controla as durações do TTL (tempo de vida útil) especificadas pelo servidor DNS. Se as entradas DNS forem alteradas regularmente, o que pode acontecer em alguns cenários, o cliente não respeitará essas atualizações. Para resolver esse problema, você pode limitar o tempo de vida da conexão definindo a propriedade PooledConnectionLifetime, de modo que a pesquisa DNS seja repetida quando a conexão for substituída. Considere o seguinte exemplo:
var handler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15) // Recreate every 15 minutes
};
var sharedClient = new HttpClient(handler);
O HttpClient
anterior é configurado para reutilizar conexões por 15 minutos. Depois que o período de tempo especificado por PooledConnectionLifetime tiver decorrido e a conexão tiver concluído sua última solicitação associada (se houver), essa conexão será encerrada. Se houver alguma solicitação aguardando na fila, uma nova conexão será criada conforme necessário.
O intervalo de 15 minutos foi escolhido arbitrariamente para fins ilustrativos. Você deve escolher o valor com base na frequência esperada de DNS ou outras alterações de rede.
Conexões em pool
O pool de conexões de um HttpClient está vinculado ao SocketsHttpHandler subjacente. Quando a instância HttpClient é descartada, ela descarta todas as conexões existentes dentro do pool. Se, posteriormente, você enviar uma solicitação para o mesmo servidor, uma nova conexão deverá ser recriada. Como resultado, há uma penalidade de desempenho para a criação de conexão desnecessária. Além disso, as portas TCP não são liberadas imediatamente após o fechamento da conexão. (Para obter mais informações sobre isso, confira o TIME-WAIT
do TCP no RFC 9293.) Se a taxa de solicitações for alta, o limite de portas disponíveis do sistema operacional poderá estar esgotado. Para evitar problemas de esgotamento de portas, recomendamos reutilizar as instâncias de HttpClient para o maior número possível de solicitações HTTP.
Uso recomendado
Para resumir o uso recomendado de HttpClient
em termos de gerenciamento de tempo de vida, você deve usar clientes de longa duração e configurar o PooledConnectionLifetime
(.NET Core e .NET 5+) ou clientes de curta duração criados por IHttpClientFactory
.
No .NET Core e .NET 5+:
- Use uma instância de
static
ou singleton HttpClient com PooledConnectionLifetime definida para o intervalo desejado, como 2 minutos, de acordo com as alterações de DNS esperadas. Isso resolve os problemas de esgotamento de portas e alterações de DNS sem adicionar a sobrecarga de IHttpClientFactory. Se você precisar simular seu manipulador, poderá registrá-lo separadamente.
Dica
Se você usar apenas um número limitado de HttpClient instâncias, essa estratégia também será aceitável. O que importa é que não sejam criadas e descartadas a cada solicitação, já que cada uma delas contém um pool de conexões. O uso de mais de uma instância é necessário para cenários com vários proxies ou para separar contêineres de cookie sem desabilitar completamente a manipulação de cookies.
Usando IHttpClientFactory, você pode ter vários clientes configurados de forma diferente para diferentes casos de uso. No entanto, lembre-se de que os clientes criados pela fábrica devem ter vida útil curta e, depois que o cliente for criado, a fábrica não terá mais controle sobre ele.
A fábrica agrupa instâncias de HttpMessageHandler e, se seu tempo de vida não tiver expirado, um manipulador poderá ser reutilizado do pool quando a fábrica criar uma nova instância de HttpClient. Essa reutilização evita problemas de esgotamento do soquete.
Se você desejar a capacidade de configuração que o IHttpClientFactory, recomendamos usar a abordagem de cliente com tipo.
- Use uma instância de
No .NET Framework, use IHttpClientFactory para gerenciar suas instâncias
HttpClient
. Se não usar o alocador e, em vez disso, criar por conta própria uma nova instância de cliente para cada solicitação, você poderá esgotar as portas disponíveis.Dica
Se seu aplicativo exigir cookies, considere desabilitar o tratamento automático de cookies ou evitar IHttpClientFactory. Agrupar as instâncias HttpMessageHandler resulta no compartilhamento de objetos CookieContainer. O compartilhamento do objeto CookieContainer de forma inesperada geralmente resulta em código incorreto.
Para obter mais informações sobre como gerenciar o tempo de vida de HttpClient
com IHttpClientFactory
, consulte as diretrizes de IHttpClientFactory
.
Resiliência com clientes estáticos
É possível configurar um cliente static
ou singleton para usar qualquer número de pipelines de resiliência usando o seguinte padrão:
using System;
using System.Net.Http;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Http.Resilience;
using Polly;
var retryPipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddRetry(new HttpRetryStrategyOptions
{
BackoffType = DelayBackoffType.Exponential,
MaxRetryAttempts = 3
})
.Build();
var socketHandler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15)
};
var resilienceHandler = new ResilienceHandler(retryPipeline)
{
InnerHandler = socketHandler,
};
var httpClient = new HttpClient(resilienceHandler);
O código anterior:
- Depende do pacote NuGet Microsoft.Extensions.Http.Resilience.
- Especifica um manipulador de erros HTTP transitório, configurado com o pipeline de repetição que, com cada tentativa, fará intervalos de atraso de retirada exponencialmente.
- Define um tempo de vida de conexão em pool de quinze minutos para o
socketHandler
. - Passa o
socketHandler
para oresilienceHandler
com a lógica de repetição. - Cria uma instância de um
HttpClient
dado umresilienceHandler
determinado.
Importante
A biblioteca de Microsoft.Extensions.Http.Resilience
está marcada como experimental e poderá mudar no futuro.