Wskazówki dotyczące korzystania z klienta HttpClient

Klasa System.Net.Http.HttpClient wysyła żądania HTTP i odbiera odpowiedzi HTTP z zasobu zidentyfikowanego przez identyfikator URI. Wystąpienie HttpClient to kolekcja ustawień, które są stosowane do wszystkich żądań wykonywanych przez to wystąpienie, a każde wystąpienie używa własnej puli połączeń, która izoluje żądania od innych. Począwszy od platformy .NET Core 2.1, SocketsHttpHandler klasa zapewnia implementację, dzięki czemu zachowanie jest spójne na wszystkich platformach.

Zachowanie dns

HttpClient Rozpoznaje tylko wpisy DNS po utworzeniu połączenia. Nie śledzi czasu wygaśnięcia (TTL) określonych przez serwer DNS. Jeśli wpisy DNS zmieniają się regularnie, co może się zdarzyć w niektórych scenariuszach, klient nie będzie przestrzegać tych aktualizacji. Aby rozwiązać ten problem, można ograniczyć okres istnienia połączenia, ustawiając PooledConnectionLifetime właściwość , aby wyszukiwanie DNS było powtarzane po zastąpieniu połączenia. Rozważmy następujący przykład:

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

Poprzednia konfiguracja HttpClient służy do ponownego używania połączeń przez 15 minut. Po upływie przedziału czasu określonego przez PooledConnectionLifetime ten czas połączenie zostanie zamknięte i zostanie utworzone nowe.

Połączenia w puli

Pula połączeń dla elementu HttpClient jest połączona z bazowym SocketsHttpHandlerelementem . HttpClient Gdy wystąpienie zostanie usunięte, usuwa wszystkie istniejące połączenia wewnątrz puli. Jeśli później wyślesz żądanie do tego samego serwera, należy ponownie utworzyć nowe połączenie. W związku z tym występuje kara za wydajność niepotrzebnego tworzenia połączenia. Ponadto porty TCP nie są zwalniane natychmiast po zamknięciu połączenia. (Aby uzyskać więcej informacji na ten temat, zobacz TCP TIME-WAIT w RFC 9293). Jeśli szybkość żądań jest wysoka, limit systemu operacyjnego dostępnych portów może zostać wyczerpany. Aby uniknąć problemów z wyczerpaniem portów, zalecamy ponowne używanie HttpClient wystąpień dla jak największej liczby żądań HTTP.

Aby podsumować zalecane HttpClient użycie w zakresie zarządzania okresem istnienia, należy użyć klientów długotrwałych i ustawić PooledConnectionLifetime (.NET Core i .NET 5+) lub krótkoterminowych klientów utworzonych przez IHttpClientFactoryprogram .

  • W programach .NET Core i .NET 5+:

    • Użyj wystąpienia pojedynczego staticHttpClient lub z PooledConnectionLifetime ustawionym żądanym interwałem, takim jak 2 minuty, w zależności od oczekiwanych zmian DNS. Rozwiązuje to zarówno problemy z wyczerpaniem portów, jak i zmianami DNS bez dodawania IHttpClientFactoryobciążenia . Jeśli musisz mieć możliwość wyśmiewać program obsługi, możesz zarejestrować go oddzielnie.

    Napiwek

    Jeśli używasz tylko ograniczonej liczby HttpClient wystąpień, jest to również akceptowalna strategia. Ważne jest, aby nie były tworzone i usuwane z każdym żądaniem, ponieważ każdy z nich zawiera pulę połączeń. Użycie więcej niż jednego wystąpienia jest niezbędne w scenariuszach z wieloma serwerami proxy lub do oddzielenia kontenerów plików cookie bez całkowitego wyłączania obsługi plików cookie.

    • Za pomocą programu IHttpClientFactorymożna mieć wielu, inaczej skonfigurowanych klientów dla różnych przypadków użycia. Należy jednak pamiętać, że klienci utworzoni przez fabrykę mają być krótkotrwałi, a po utworzeniu klienta fabryka nie ma już nad nią kontroli.

      Wystąpienia pul HttpMessageHandler fabryki i, jeśli jego okres istnienia nie wygasł, program obsługi można użyć ponownie z puli, gdy fabryka utworzy nowe HttpClient wystąpienie. Ponowne użycie pozwala uniknąć problemów z wyczerpaniem gniazd.

      Jeśli chcesz, aby IHttpClientFactory zapewnić możliwość konfigurowania, zalecamy użycie podejścia typizowanego klienta.

  • W programie .NET Framework użyj polecenia IHttpClientFactory do zarządzania wystąpieniami HttpClient . Jeśli nie używasz fabryki i zamiast tego utworzysz nowe wystąpienie klienta dla każdego żądania samodzielnie, możesz wyczerpać dostępne porty.

    Napiwek

    Jeśli aplikacja wymaga plików cookie, rozważ wyłączenie automatycznej obsługi plików cookie lub uniknięcie .IHttpClientFactory Buforowanie HttpMessageHandler wystąpień powoduje udostępnianie CookieContainer obiektów. Nieprzewidziane CookieContainer udostępnianie obiektów często powoduje niepoprawny kod.

Aby uzyskać więcej informacji na temat zarządzania okresem HttpClient istnienia za pomocą IHttpClientFactoryprogramu , zobacz IHttpClientFactory wytyczne.

Odporność na statycznych klientów

Istnieje możliwość skonfigurowania pojedynczego static klienta lub do używania dowolnej liczby potoków odporności przy użyciu następującego wzorca:

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

Powyższy kod ma następujące działanie:

  • Opiera się na pakiecie NuGet Microsoft.Extensions.Http.Resilience .
  • Określa przejściową procedurę obsługi błędów HTTP, skonfigurowaną przy użyciu potoku ponawiania, który z każdą próbą będzie wykładniczo opóźniać wycofywanie.
  • Definiuje okres istnienia połączenia w puli w ciągu piętnastu minut dla elementu socketHandler.
  • Przekazuje element socketHandler do resilienceHandler elementu za pomocą logiki ponawiania.
  • Tworzy wystąpienie danego HttpClient elementu resilienceHandler.

Ważne

Biblioteka Microsoft.Extensions.Http.Resilience jest obecnie oznaczona jako eksperymentalna i może ulec zmianie w przyszłości.

Zobacz też