Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
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 acompanha as durações 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, limite o tempo de vida da conexão definindo a propriedade, de modo que a PooledConnectionLifetime pesquisa de DNS seja repetida quando a conexão for substituída. Considere este 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 especificado pelo PooledConnectionLifetime decorrido e a conexão tiver concluído sua última solicitação associada (se houver), a conexão será fechada. 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
staticou singletonHttpClient 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.Aviso
Se o seu aplicativo exigir cookies, é recomendável evitar o uso de IHttpClientFactory. Agrupar as instâncias HttpMessageHandler resulta no compartilhamento de objetos CookieContainer. O compartilhamento imprevisto CookieContainer pode vazar cookies entre partes não relacionadas do aplicativo. Além disso, quando HandlerLifetime expira, o handler é reciclado, o que significa que todos os cookies armazenados em seu CookieContainer são apagados.
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 Microsoft.Extensions.Http.Resilience;
using Polly;
class MyClass
{
static HttpClient? s_httpClient;
MyClass()
{
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,
};
s_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
socketHandlerpara oresilienceHandlercom a lógica de repetição. - Cria uma instância de
HttpClientcompartilhada dado oresilienceHandler.