Riktlinjer för att använda HttpClient

Klassen System.Net.Http.HttpClient skickar HTTP-begäranden och tar emot HTTP-svar från en resurs som identifieras av en URI. En HttpClient instans är en samling inställningar som tillämpas på alla begäranden som körs av den instansen, och varje instans använder sin egen anslutningspool, som isolerar dess begäranden från andra. Från och med .NET Core 2.1 SocketsHttpHandler tillhandahåller klassen implementeringen, vilket gör beteendet konsekvent på alla plattformar.

DNS-beteende

HttpClient löser bara DNS-poster när en anslutning skapas. Den spårar inte tidsåtgången (TTL) som angetts av DNS-servern. Om DNS-poster ändras regelbundet, vilket kan inträffa i vissa scenarier, kommer klienten inte att respektera dessa uppdateringar. För att lösa det här problemet kan du begränsa anslutningens livslängd genom att ange PooledConnectionLifetime egenskapen så att DNS-sökningen upprepas när anslutningen ersätts. Ta följande som exempel:

var handler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(15) // Recreate every 15 minutes
};
var sharedClient = new HttpClient(handler);

Föregående HttpClient är konfigurerat för att återanvända anslutningar i 15 minuter. När tidsintervallet som anges av PooledConnectionLifetime har förflutit stängs anslutningen och en ny skapas.

Poolanslutningar

Anslutningspoolen för en HttpClient är länkad till den underliggande SocketsHttpHandler. När instansen HttpClient tas bort tas alla befintliga anslutningar i poolen bort. Om du senare skickar en begäran till samma server måste en ny anslutning återskapas. Det innebär att det finns en prestandaavgift för att skapa onödiga anslutningar. Dessutom släpps inte TCP-portar omedelbart efter att anslutningen har stängts. (Mer information om detta finns i TCP TIME-WAIT i RFC 9293.) Om antalet begäranden är hög kan operativsystemets gräns för tillgängliga portar vara uttömd. För att undvika portöverbelastningsproblem rekommenderar vi att HttpClient du återanvänder instanser för så många HTTP-begäranden som möjligt.

Om du vill sammanfatta rekommenderad HttpClient användning när det gäller livslängdshantering bör du använda antingen långlivade klienter och ange PooledConnectionLifetime (.NET Core och .NET 5+) eller kortlivade klienter som skapats av IHttpClientFactory.

  • I .NET Core och .NET 5+:

    • Använd en static eller singleton-instansHttpClient med PooledConnectionLifetime inställt på önskat intervall, till exempel 2 minuter, beroende på förväntade DNS-ändringar. Detta löser både problem med portöverbelastning och DNS-ändringar utan att lägga till omkostnaderna IHttpClientFactoryför . Om du behöver kunna håna hanteraren kan du registrera den separat.

    Dricks

    Om du bara använder ett begränsat antal HttpClient instanser är det också en acceptabel strategi. Det viktiga är att de inte skapas och tas bort med varje begäran, eftersom de var och en innehåller en anslutningspool. Att använda mer än en instans är nödvändigt för scenarier med flera proxyservrar eller för att separera cookiecontainrar utan att helt inaktivera cookiehantering.

    • Med kan IHttpClientFactorydu ha flera, olika konfigurerade klienter för olika användningsfall. Tänk dock på att de fabriksskapade klienterna är avsedda att vara kortvariga, och när klienten har skapats har fabriken inte längre kontroll över den.

      Fabrikspoolinstanserna HttpMessageHandler , och om dess livslängd inte har upphört att gälla kan en hanterare återanvändas från poolen när fabriken skapar en ny HttpClient instans. Den här återanvändning undviker problem med socketöverbelastning.

      Om du vill ha den konfigurerbarhet som finns rekommenderar vi att IHttpClientFactory du använder metoden typed-client.

  • I .NET Framework använder du IHttpClientFactory för att hantera dina HttpClient instanser. Om du inte använder fabriken och i stället skapar en ny klientinstans för varje begäran själv kan du tömma tillgängliga portar.

    Dricks

    Om din app kräver cookies kan du överväga att inaktivera automatisk cookiehantering eller undvika IHttpClientFactory. Poolning av HttpMessageHandler instanser resulterar i delning av CookieContainer objekt. Oväntad CookieContainer objektdelning resulterar ofta i felaktig kod.

Mer information om hur du hanterar HttpClient livslängden med IHttpClientFactoryfinns i IHttpClientFactory riktlinjer.

Motståndskraft med statiska klienter

Det är möjligt att konfigurera en eller singleton-klient static att använda valfritt antal resilienspipelines med hjälp av följande mönster:

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);

Koden ovan:

  • Förlitar sig på Microsoft.Extensions.Http.Resilience NuGet-paketet.
  • Anger en tillfällig HTTP-felhanterare, konfigurerad med en pipeline för återförsök som med varje försök exponentiellt kommer att backoff fördröja intervallen.
  • Definierar en poolanslutningstid på 15 minuter för socketHandler.
  • socketHandler Skickar till resilienceHandler med logiken för återförsök.
  • Instansierar en HttpClient angiven resilienceHandler.

Viktigt!

Biblioteket Microsoft.Extensions.Http.Resilience är för närvarande markerat som experimentellt och kan ändras i framtiden.

Se även