Diretrizes para usar HttpClient

A System.Net.Http.HttpClient classe envia solicitações HTTP e recebe respostas HTTP de um recurso identificado por um URI. Uma HttpClient instância é uma coleção de configurações que é aplicada a todas as solicitações executadas por essa instância, e cada instância usa seu próprio pool de conexões, que isola suas solicitações de outras. A partir do .NET Core 2.1, a SocketsHttpHandler classe fornece a implementação, tornando o comportamento consistente em todas as plataformas.

Comportamento do DNS

HttpClient só resolve entradas DNS quando uma conexão é criada. Ele não rastreia nenhuma duração de tempo de vida (TTL) especificada 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, para que a PooledConnectionLifetime pesquisa de 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 anterior HttpClient está 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á 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 agrupadas

O pool de conexões de um HttpClient está vinculado ao .SocketsHttpHandler Quando a HttpClient instância é 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, consulte TCP TIME-WAIT no RFC 9293.) Se a taxa de solicitações for alta, o limite do sistema operacional de portas disponíveis pode estar esgotado. Para evitar problemas de exaustão de portas, recomendamos reutilizar HttpClient instâncias para o maior número possível de solicitações HTTP.

Para resumir o uso recomendado HttpClient em termos de gerenciamento de tempo de vida, você deve usar clientes de longa duração e definir PooledConnectionLifetime (.NET Core e .NET 5+) ou clientes de curta duração criados pela IHttpClientFactory.

  • No .NET Core e no .NET 5+:

    • Use uma static instância ou singleton HttpClient com PooledConnectionLifetime definido para o intervalo desejado, como 2 minutos, dependendo das alterações de DNS esperadas. Isso resolve os problemas de exaustão da porta e alterações de DNS sem adicionar a sobrecarga do IHttpClientFactory. Se você precisar ser capaz de simular seu manipulador, você pode registrá-lo separadamente.

    Gorjeta

    Se você usar apenas um número limitado de HttpClient instâncias, essa também é uma estratégia aceitável. O que importa é que eles não são criados e descartados a cada solicitação, pois cada um deles 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 cookies sem desabilitar completamente o tratamento de cookies.

    • Usando IHttpClientFactoryo , você pode ter vários clientes configurados de forma diferente para diferentes casos de uso. No entanto, esteja ciente de que os clientes criados na fábrica devem ser de curta duração e, uma vez que o cliente é criado, a fábrica não tem mais controle sobre ele.

      As instâncias dos pools HttpMessageHandler de fábrica e, se sua vida útil não tiver expirado, um manipulador poderá ser reutilizado do pool quando a fábrica criar uma nova HttpClient instância. Essa reutilização evita problemas de exaustão do soquete.

      Se você deseja a configurabilidade que IHttpClientFactory fornece, recomendamos usar a abordagem typed-client.

  • No .NET Framework, use IHttpClientFactory para gerenciar suas HttpClient instâncias. Se você não usar a fábrica e, em vez disso, criar uma nova instância de cliente para cada solicitação, poderá esgotar as portas disponíveis.

    Gorjeta

    Se a sua aplicação necessitar de cookies, considere desativar o tratamento automático de cookies ou evitar IHttpClientFactoryo . O agrupamento das HttpMessageHandler instâncias resulta no compartilhamento de CookieContainer objetos. O compartilhamento imprevisto CookieContainer de objetos geralmente resulta em código incorreto.

Para obter mais informações sobre como gerenciar o HttpClient tempo de vida com IHttpClientFactoryo , consulte IHttpClientFactory as diretrizes.

Resiliência com clientes estáticos

É possível configurar um static cliente 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 erro HTTP transitório, configurado com pipeline de repetição que, a cada tentativa, recuará exponencialmente os intervalos de atraso.
  • Define uma vida útil de conexão agrupada de quinze minutos para o socketHandler.
  • Passa a socketHandler lógica para o resilienceHandler com a repetição.
  • Instancia um HttpClient dado o resilienceHandler.

Importante

A Microsoft.Extensions.Http.Resilience biblioteca está atualmente marcada como experimental e pode mudar no futuro.

Consulte também