System.Net.Http.HttpClient, klasa

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Wystąpienie klasy działa jako sesja HttpClient wysyłania żądań HTTP. Wystąpienie HttpClient to kolekcja ustawień zastosowanych do wszystkich żądań wykonywanych przez to wystąpienie. Ponadto każde HttpClient wystąpienie używa własnej puli połączeń, izolując żądania od żądań wykonywanych przez inne HttpClient wystąpienia.

Tworzenie wystąpienia

HttpClient jest przeznaczony do utworzenia wystąpienia raz i ponownego użycia przez cały czas stosowania. W programach .NET Core i .NET 5 lub nowszych pule HttpClient wewnątrz wystąpienia programu obsługi i ponownie używa połączenia między wieloma żądaniami. Jeśli utworzysz wystąpienie klasy HttpClient dla każdego żądania, liczba gniazd dostępnych pod dużym obciążeniem zostanie wyczerpana. To wyczerpanie spowoduje SocketException błędy.

Dodatkowe opcje można skonfigurować, przekazując "program obsługi", taki jak HttpClientHandler (lub SocketsHttpHandler w programie .NET Core 2.1 lub nowszym) jako część konstruktora. Właściwości połączenia w programie obsługi nie można zmienić po przesłaniu żądania, dlatego jednym z powodów utworzenia nowego wystąpienia klienta HttpClient byłoby zmiana właściwości połączenia. Jeśli różne żądania wymagają różnych ustawień, może to również prowadzić do tego, że aplikacja ma wiele HttpClient wystąpień, w których każde wystąpienie jest odpowiednio skonfigurowane, a następnie żądania są wystawiane na odpowiednim kliencie.

Klient 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 kontenera, klient nie będzie przestrzegać tych aktualizacji. Aby rozwiązać ten problem, można ograniczyć okres istnienia połączenia, ustawiając SocketsHttpHandler.PooledConnectionLifetime właściwość , aby wyszukiwanie DNS było wymagane po zastąpieniu połączenia.

public class GoodController : ApiController
{
    private static readonly HttpClient httpClient;

    static GoodController()
    {
        var socketsHandler = new SocketsHttpHandler
        {
            PooledConnectionLifetime = TimeSpan.FromMinutes(2)
        };

        httpClient = new HttpClient(socketsHandler);
    }
}

Alternatywą dla tworzenia tylko jednego wystąpienia klienta HttpClient jest również IHttpClientFactory zarządzanie wystąpieniami klienta HttpClient. Aby uzyskać więcej informacji, zobacz Wytyczne dotyczące korzystania z obiektu HttpClient.

Pochodne

Element HttpClient działa również jako klasa bazowa dla bardziej określonych klientów HTTP. Przykładem może być FacebookHttpClient, który udostępnia dodatkowe metody specyficzne dla usługi internetowej serwisu Facebook (na przykład GetFriends metody). Klasy pochodne nie powinny zastępować metod wirtualnych w klasie. Zamiast tego należy użyć przeciążenia konstruktora, który akceptuje HttpMessageHandler , aby skonfigurować przetwarzanie przed żądaniem lub po żądaniu.

Transporty

Jest HttpClient to interfejs API wysokiego poziomu, który opakowuje funkcje niższego poziomu dostępne na każdej platformie, na której działa.

Na każdej platformie HttpClient próbuje skorzystać z najlepszego dostępnego transportu:

Host/środowisko uruchomieniowe Zaplecza
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Natywna wersja WinHttpHandler systemu Windows (z obsługą protokołu HTTP 2.0)
Windows/.NET Core 1.0-2.0 Natywna wersja WinHttpHandler systemu Windows (z obsługą protokołu HTTP 2.0)
Android/Xamarin Wybrane w czasie kompilacji. Można użyć lub HttpWebRequest skonfigurować do używania natywnego systemu Android HttpURLConnection
iOS, tvOS, watchOS/Xamarin Wybrane w czasie kompilacji. Można użyć HttpWebRequest lub skonfigurować do korzystania z urządzeń NSUrlSession firmy Apple (z obsługą protokołu HTTP 2.0)
macOS/Xamarin Wybrane w czasie kompilacji. Można użyć HttpWebRequest lub skonfigurować do korzystania z urządzeń NSUrlSession firmy Apple (z obsługą protokołu HTTP 2.0)
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurlTransport HTTP oparty na protokole HTTP (z obsługą protokołu HTTP 2.0)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurlTransport HTTP oparty na protokole HTTP (z obsługą protokołu HTTP 2.0)
.NET Core 2.1 lub nowszy System.Net.Http.SocketsHttpHandler

Użytkownicy mogą również skonfigurować określony transport przez HttpClient wywołanie konstruktora HttpClientHttpMessageHandler, który przyjmuje element .

.NET Framework i Mono

Domyślnie w programach .NET Framework i Mono HttpWebRequest jest używana do wysyłania żądań do serwera. To zachowanie można zmodyfikować, określając inną procedurę obsługi w jednym z przeciążeń konstruktora za pomocą parametru HttpMessageHandler . Jeśli potrzebujesz funkcji, takich jak uwierzytelnianie lub buforowanie, możesz użyć WebRequestHandler polecenia , aby skonfigurować ustawienia i wystąpienie można przekazać do konstruktora. Zwróconą procedurę obsługi można przekazać do przeciążenia konstruktora z parametrem HttpMessageHandler .

.NET Core

Począwszy od platformy .NET Core 2.1, System.Net.Http.SocketsHttpHandler klasa zamiast HttpClientHandler zapewnia implementację używaną przez klasy sieci HTTP wyższego poziomu, takie jak HttpClient. Korzystanie z SocketsHttpHandler ofert ma wiele zalet:

  • Znacząca poprawa wydajności w porównaniu z poprzednią implementacją.
  • Eliminacja zależności platformy, która upraszcza wdrażanie i obsługę. Na przykład libcurl nie jest to już zależność od platformy .NET Core dla systemów macOS i .NET Core dla systemu Linux.
  • Spójne zachowanie na wszystkich platformach .NET.

Jeśli ta zmiana jest niepożądane, w systemie Windows można nadal używać WinHttpHandler , odwołując się do jego pakietu NuGet i przekazując go ręcznie do konstruktora HttpClient.

Konfigurowanie zachowania przy użyciu opcji konfiguracji środowiska uruchomieniowego

Niektóre aspekty HttpClientzachowania można dostosowywać za pomocą opcji konfiguracji środowiska uruchomieniowego. Jednak zachowanie tych przełączników różni się w zależności od wersji platformy .NET. Na przykład w programie .NET Core 2.1 — 3.1 można skonfigurować, czy SocketsHttpHandler jest używany domyślnie, ale ta opcja nie jest już dostępna, począwszy od platformy .NET 5.

Buforowanie połączeń

Klient HTTP pule połączeń HTTP tam, gdzie to możliwe, i używa ich dla więcej niż jednego żądania. Może to mieć znaczną korzyść z wydajności, zwłaszcza w przypadku żądań HTTPS, ponieważ uzgadnianie połączenia odbywa się tylko raz.

właściwości puli Połączenie ion można skonfigurować na HttpClientHandler obiekcie lub SocketsHttpHandler przekazanym podczas budowy, w tym MaxConnectionsPerServer, PooledConnectionIdleTimeouti PooledConnectionLifetime.

Usunięcie wystąpienia httpClient zamyka otwarte połączenia i anuluje wszystkie oczekujące żądania.

Uwaga

Jeśli jednocześnie wysyłasz żądania HTTP/1.1 do tego samego serwera, można utworzyć nowe połączenia. Nawet w przypadku ponownego HttpClient użycia wystąpienia, jeśli szybkość żądań jest wysoka lub istnieją jakiekolwiek ograniczenia zapory, które mogą wyczerpać dostępne gniazda z powodu domyślnych czasomierzy oczyszczania TCP. Aby ograniczyć liczbę połączeń współbieżnych, możesz ustawić MaxConnectionsPerServer właściwość . Domyślnie liczba współbieżnych połączeń HTTP/1.1 jest nieograniczona.

Buforowanie i okres istnienia żądania

Domyślnie metody HttpClient (z wyjątkiem GetStreamAsync) buforu odpowiedzi z serwera, odczytując całą treść odpowiedzi do pamięci przed zwróceniem wyniku asynchronicznego. Te żądania będą kontynuowane do momentu wystąpienia jednego z następujących elementów:

Zachowanie buforowania można zmienić dla poszczególnych żądań przy użyciu parametru dostępnego HttpCompletionOption w niektórych przeciążeniach metody. Ten argument może służyć do określenia, czy Task<TResult> element powinien zostać uznany za ukończony po przeczytaniu tylko nagłówków odpowiedzi, czy po odczytaniu i buforowaniu zawartości odpowiedzi.

Jeśli aplikacja używająca HttpClient i powiązanych klas w System.Net.Http przestrzeni nazw zamierza pobrać duże ilości danych (50 megabajtów lub więcej), aplikacja powinna przesyłać strumieniowo te pliki do pobrania i nie używać buforowania domyślnego. Jeśli używasz buforowania domyślnego, użycie pamięci klienta będzie bardzo duże, co może spowodować znaczne zmniejszenie wydajności.

Bezpieczeństwo wątkowe

Następujące metody są bezpieczne wątkami:

Serwery proxy

Domyślnie klient HttpClient odczytuje konfigurację serwera proxy ze zmiennych środowiskowych lub ustawień użytkownika/systemu, w zależności od platformy. To zachowanie można zmienić, przekazując element WebProxy lub IWebProxy w kolejności pierwszeństwa:

  • Właściwość Proxy w programie HttpClientHandler przekazanym podczas budowy obiektu HttpClient
  • Właściwość statyczna DefaultProxy (dotyczy wszystkich wystąpień)

Serwer proxy można wyłączyć przy użyciu polecenia UseProxy. Domyślną konfiguracją dla użytkowników systemu Windows jest wypróbowanie i wykrycie serwera proxy przy użyciu odnajdywania sieci, co może być powolne. W przypadku aplikacji o wysokiej przepływności, w których wiadomo, że serwer proxy nie jest wymagany, należy wyłączyć serwer proxy.

Ustawienia serwera proxy (na przykład Credentials) powinny zostać zmienione dopiero przed wykonaniem pierwszego żądania przy użyciu klienta HttpClient. Zmiany wprowadzone po pierwszym użyciu obiektu HttpClient mogą nie zostać odzwierciedlone w kolejnych żądaniach.

Limity czasu

Możesz użyć Timeout polecenia , aby ustawić domyślny limit czasu dla wszystkich żądań HTTP z wystąpienia klienta HttpClient. Limit czasu dotyczy tylko metod xxxAsync, które powodują zainicjowanie żądania/odpowiedzi. Jeśli limit czasu zostanie osiągnięty, Task<TResult> żądanie zostanie anulowane.

Dodatkowe limity czasu można ustawić w SocketsHttpHandler przypadku przekazania wystąpienia podczas konstruowania obiektu HttpClient:

Właściwości opis
ConnectTimeout Określa limit czasu używany, gdy żądanie wymaga utworzenia nowego połączenia TCP. Jeśli wystąpi przekroczenie limitu czasu, żądanie Task<TResult> zostanie anulowane.
PooledConnectionLifetime Określa limit czasu, który ma być używany dla każdego połączenia w puli połączeń. Jeśli połączenie jest bezczynne, połączenie zostanie natychmiast zamknięte; w przeciwnym razie połączenie jest zamykane na końcu bieżącego żądania.
PooledConnectionIdleTimeout Jeśli połączenie w puli połączeń jest bezczynne przez ten czas, połączenie zostanie zamknięte.
Expect100ContinueTimeout Jeśli żądanie ma nagłówek "Oczekiwano: 100-continue", opóźnia wysyłanie zawartości do momentu przekroczenia limitu czasu lub do odebrania odpowiedzi "100-continue".

Klient HttpClient rozpoznaje tylko wpisy DNS podczas tworzenia połączeń. 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 kontenera, można użyć parametru PooledConnectionLifetime , aby ograniczyć okres istnienia połączenia, aby wyszukiwanie DNS było wymagane podczas zastępowania połączenia.