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 någon livslängd (TTL) som angivits 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 och anslutningen har slutfört sin senaste associerade begäran (om någon) stängs den här anslutningen. Om det finns begäranden som väntar i kön skapas en ny anslutning efter behov.
Intervallet på 15 minuter valdes godtyckligt för illustrationsändamål. Du bör välja värdet baserat på den förväntade frekvensen för DNS eller andra nätverksändringar.
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.
Rekommenderad användning
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 för IHttpClientFactory. 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.
Fabriken poolar HttpMessageHandler-instanser, och om deras livslängd inte har gått ut 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 önskar den konfigurerbarhet som IHttpClientFactory erbjuder, rekommenderar vi att du använder metoden typed-client.
- Använd en
I .NET Framework använder du IHttpClientFactory för att hantera dina
HttpClient
instanser. Om du inte använder fabriken och i stället själv skapar en ny klient för varje begäran, kan du tömma tillgängliga portar.Tips
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 IHttpClientFactory
finns i IHttpClientFactory
riktlinjer.
Motståndskraft med statiska klienter
Det är möjligt att konfigurera en static
eller singleton-klient att använda valfritt antal resilienspipelines med hjälp av följande mönster:
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);
}
}
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 kommer att exponentiellt öka förseningarna.
- Definierar en poolanslutningstid på 15 minuter för
socketHandler
. - Skickar vidare
socketHandler
tillresilienceHandler
tillsammans med omförsökslogiken. - Instansierar en delad
HttpClient
givetresilienceHandler
.
Viktigt!
Microsoft.Extensions.Http.Resilience
-biblioteket är för närvarande markerat som experimentella och kan komma att ändras i framtiden.