Sdílet prostřednictvím


System.Net.Http.HttpClient – třída

Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.

Instance HttpClient třídy funguje jako relace pro odesílání požadavků HTTP. Instance HttpClient je kolekce nastavení použitá pro všechny požadavky spuštěné danou instancí. Každá instance navíc HttpClient používá vlastní fond připojení a izoluje své požadavky z požadavků spuštěných jinými HttpClient instancemi.

Vytváření instancí

HttpClient je určena k vytvoření instance jednou a opakovanému použití v průběhu celé životnosti aplikace. V .NET Core a .NET 5 nebo novějších, HttpClient fondy připojení uvnitř instance obslužné rutiny a opakovaně používá připojení napříč několika požadavky. Pokud vytvoříte instanci třídy HttpClient pro každý požadavek, počet soketů dostupných při velkém zatížení bude vyčerpán. Výsledkem tohoto vyčerpání budou SocketException chyby.

Další možnosti můžete nakonfigurovat předáním "obslužné rutiny", například v SocketsHttpHandler .NET Core 2.1 nebo novějším), jako HttpClientHandler je součást konstruktoru. Vlastnosti připojení v obslužné rutině nelze po odeslání požadavku změnit, takže jedním z důvodů vytvoření nové instance HttpClient by bylo, kdybyste potřebovali změnit vlastnosti připojení. Pokud různé požadavky vyžadují různá nastavení, může to také vést k tomu, že aplikace má více HttpClient instancí, kde je každá instance správně nakonfigurovaná, a pak se požadavky vydávají na příslušném klientovi.

HttpClient překládá pouze položky DNS při vytvoření připojení. Nesleduje dobu trvání TTL (Time To Live) určenou serverem DNS. Pokud se položky DNS mění pravidelně, což se může stát v některých scénářích kontejneru, klient tyto aktualizace nerespektuje. Chcete-li tento problém vyřešit, můžete omezit dobu životnosti připojení nastavením SocketsHttpHandler.PooledConnectionLifetime vlastnosti, aby při nahrazení připojení bylo vyžadováno vyhledávání DNS.

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

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

        httpClient = new HttpClient(socketsHandler);
    }
}

Jako alternativu k vytvoření pouze jedné instance HttpClient můžete také použít IHttpClientFactory ke správě instancí HttpClient za vás. Další informace naleznete v tématu Pokyny pro použití HttpClient.

Derivace

Funguje HttpClient také jako základní třída pro konkrétnější klienty HTTP. Příkladem může být FacebookHttpClient, který poskytuje další metody specifické pro webovou službu Facebooku (například metodu GetFriends ). Odvozené třídy by neměly přepsat virtuální metody ve třídě. Místo toho použijte přetížení konstruktoru, které přijímá HttpMessageHandler ke konfiguraci jakéhokoli předběžného požadavku nebo následného zpracování požadavku.

Přenosy

Jedná se HttpClient o rozhraní API vysoké úrovně, které zabalí funkce nižší úrovně dostupné na každé platformě, kde běží.

Na každé platformě HttpClient se pokusí použít nejlepší dostupnou dopravu:

Hostitel/modul runtime Backend
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UPW Nativní WinHttpHandler windows (podporuje HTTP 2.0)
Windows/.NET Core 1.0-2.0 Nativní WinHttpHandler windows (podporuje HTTP 2.0)
Android/Xamarin Vybráno v době sestavení. Můžete použít HttpWebRequest nebo nakonfigurovat, aby používal nativní Android. HttpURLConnection
iOS, tvOS, watchOS/Xamarin Vybráno v době sestavení. Můžete ho použít HttpWebRequest nebo nakonfigurovat tak, aby používal apple NSUrlSession (podporuje HTTP 2.0).
macOS/Xamarin Vybráno v době sestavení. Můžete ho použít HttpWebRequest nebo nakonfigurovat tak, aby používal apple NSUrlSession (podporuje HTTP 2.0).
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurlna základě přenosu HTTP (podporuje HTTP 2.0)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurlna základě přenosu HTTP (podporuje HTTP 2.0)
.NET Core 2.1 a novější System.Net.Http.SocketsHttpHandler

Uživatelé mohou také nakonfigurovat konkrétní přenos pro HttpClient vyvolání HttpClient konstruktoru, který přebírá .HttpMessageHandler

.NET Framework & Mono

Ve výchozím nastavení se v rozhraní .NET Framework a Mono HttpWebRequest používá k odesílání požadavků na server. Toto chování lze upravit zadáním jiné obslužné rutiny v jednom z konstruktor přetížení s parametrem HttpMessageHandler . Pokud požadujete funkce, jako je ověřování nebo ukládání do mezipaměti, můžete použít WebRequestHandler ke konfiguraci nastavení a instanci lze předat konstruktoru. Vrácenou obslužnou rutinu lze předat do přetížení konstruktoru HttpMessageHandler , který má parametr.

.NET Core

Počínaje rozhraním .NET Core 2.1 poskytuje třída místo HttpClientHandler implementace používanou vyšší úrovní síťových tříd HTTP, System.Net.Http.SocketsHttpHandler jako HttpClientje . Použití SocketsHttpHandler nabídky nabízí řadu výhod:

  • Významné zlepšení výkonu v porovnání s předchozí implementací.
  • Odstranění závislostí platformy, které zjednodušuje nasazení a údržbu. Například libcurl už není závislost na .NET Core pro macOS a .NET Core pro Linux.
  • Konzistentní chování na všech platformách .NET

Pokud je tato změna nežádoucí, můžete ve Windows pokračovat v používání WinHttpHandler odkazováním na jeho balíček NuGet a jeho předáním do konstruktoru HttpClient ručně.

Konfigurace chování pomocí možností konfigurace modulu runtime

Některé aspekty HttpClientchování se dají přizpůsobit prostřednictvím možností konfigurace modulu runtime. Chování těchto přepínačů se ale liší v různých verzích .NET. Například v .NET Core 2.1 – 3.1 můžete nakonfigurovat, jestli SocketsHttpHandler se používá ve výchozím nastavení, ale tato možnost už není dostupná od .NET 5.

Sdružování připojení

HttpClient sloučí připojení HTTP, pokud je to možné, a používá je pro více než jeden požadavek. To může mít významnou výhodu výkonu, zejména pro požadavky HTTPS, protože handshake připojení se provádí pouze jednou.

vlastnosti Připojení ionového fondu lze konfigurovat na objektu HttpClientHandler nebo SocketsHttpHandler předaném během výstavby, včetně MaxConnectionsPerServer, PooledConnectionIdleTimeouta PooledConnectionLifetime.

Odstranění instance HttpClient zavře otevřená připojení a zruší všechny čekající požadavky.

Poznámka:

Pokud souběžně odesíláte požadavky HTTP/1.1 na stejný server, můžete vytvořit nová připojení. I když instanci znovu použijete HttpClient , pokud je rychlost požadavků vysoká nebo pokud existují nějaká omezení brány firewall, můžou dostupné sokety vyčerpat kvůli výchozím časovačům čištění protokolu TCP. Chcete-li omezit počet souběžných připojení, můžete nastavit MaxConnectionsPerServer vlastnost. Ve výchozím nastavení je počet souběžných připojení HTTP/1.1 neomezený.

Ukládání do vyrovnávací paměti a doba života požadavků

Ve výchozím nastavení metody HttpClient (s výjimkou GetStreamAsync) vyrovnávací paměti odpovědi ze serveru, čtení veškerého těla odpovědi do paměti před vrácením asynchronního výsledku. Tyto požadavky budou pokračovat, dokud nedojde k některému z následujících kroků:

Chování ukládání do vyrovnávací paměti pro jednotlivé požadavky můžete změnit pomocí parametru dostupného HttpCompletionOption v některých přetíženích metody. Tento argument lze použít k určení, jestli Task<TResult> se má považovat za dokončený po přečtení pouze hlaviček odpovědi nebo po přečtení a uložení obsahu odpovědi do vyrovnávací paměti.

Pokud vaše aplikace, která používá HttpClient a související třídy v System.Net.Http oboru názvů hodlá stáhnout velké objemy dat (50 megabajtů nebo více), měla by aplikace streamovat tyto soubory ke stažení a nepoužívat výchozí ukládání do vyrovnávací paměti. Pokud použijete výchozí ukládání do vyrovnávací paměti, bude využití paměti klienta velmi velké, což může mít za následek podstatně nižší výkon.

Bezpečnost vlákna

Následující metody jsou bezpečné pro přístup z více vláken:

Proxy

Ve výchozím nastavení httpClient čte konfiguraci proxy serveru z proměnných prostředí nebo nastavení uživatele/systému v závislosti na platformě. Toto chování můžete změnit předáním WebProxy nebo IWebProxy předáním priority:

  • Vlastnost Proxy httpClientHandler předána během vytváření HttpClient
  • Statická DefaultProxy vlastnost (ovlivňuje všechny instance)

Proxy server můžete zakázat pomocí UseProxy. Výchozí konfigurací pro uživatele Windows je vyzkoušet a zjistit proxy pomocí zjišťování sítě, což může být pomalé. U aplikací s vysokou propustností, u kterých je známo, že proxy server není nutný, byste proxy měli zakázat.

Nastavení proxy serveru (například Credentials) by se mělo změnit pouze před provedením prvního požadavku pomocí HttpClient. Změny provedené po prvním použití HttpClient se nemusí v následných požadavcích projevit.

Časové limity

Můžete použít Timeout k nastavení výchozího časového limitu pro všechny požadavky HTTP z instance HttpClient. Časový limit se vztahuje pouze na metody xxxAsync, které způsobují zahájení požadavku nebo odpovědi. Pokud dojde k dosažení časového limitu Task<TResult> , zruší se žádost.

Pokud předáte instanci při vytváření objektu SocketsHttpHandler HttpClient, můžete nastavit několik dalších časových limitů:

Vlastnost Popis
ConnectTimeout Určuje časový limit, který se použije, když požadavek vyžaduje vytvoření nového připojení TCP. Pokud dojde k vypršení časového limitu, žádost Task<TResult> se zruší.
PooledConnectionLifetime Určuje časový limit, který se má použít pro každé připojení ve fondu připojení. Pokud je připojení nečinné, připojení je okamžitě uzavřeno; v opačném případě je připojení uzavřeno na konci aktuálního požadavku.
PooledConnectionIdleTimeout Pokud je připojení ve fondu připojení pro tuto dobu nečinné, připojení se zavře.
Expect100ContinueTimeout Pokud má požadavek hlavičku "Expect: 100-continue", zpožďuje odesílání obsahu do časového limitu nebo do přijetí odpovědi "100-continue".

HttpClient překládá pouze položky DNS při vytváření připojení. Nesleduje dobu trvání TTL (Time To Live) určenou serverem DNS. Pokud se položky DNS pravidelně mění, což se může stát v některých scénářích kontejneru, můžete použít PooledConnectionLifetime k omezení doby životnosti připojení, aby se při nahrazení připojení vyžadovalo vyhledávání DNS.