A HttpClient használatának irányelvei

Az System.Net.Http.HttpClient osztály HTTP-kéréseket küld, és HTTP-válaszokat fogad egy URI által azonosított erőforrástól. A HttpClient példányok az adott példány által végrehajtott összes kérésre alkalmazott beállítások gyűjteményei, és minden példány saját kapcsolatkészletet használ, amely elkülöníti a kéréseket másoktól. A .NET Core 2.1-től kezdve az osztály biztosítja a SocketsHttpHandler megvalósítást, így a viselkedés minden platformon konzisztens.

DNS-viselkedés

HttpClient csak kapcsolat létrehozásakor oldja fel a DNS-bejegyzéseket. A DNS-kiszolgáló által megadott élettartamokat (TTL) nem követi nyomon. Ha a DNS-bejegyzések rendszeresen változnak, ami bizonyos esetekben előfordulhat, az ügyfél nem fogja tiszteletben tartani ezeket a frissítéseket. A probléma megoldásához korlátozza a kapcsolat élettartamát a tulajdonság beállításával, hogy a PooledConnectionLifetime DNS-keresés ismétlődjön a kapcsolat cseréjekor. Fontolja meg ezt a példát:

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

A fenti HttpClient beállítás a kapcsolatok 15 percig történő újrafelhasználására van konfigurálva. Miután a megadott PooledConnectionLifetime idő eltelt, és a kapcsolat befejezte az utolsó társított kérését (ha van ilyen), a kapcsolat lezárul. Ha bármilyen kérés várakozik az üzenetsorban, szükség szerint létrejön egy új kapcsolat.

A 15 perces időközt tetszőlegesen választottuk illusztrációs célokra. Az értéket a DNS vagy más hálózati változások várható gyakorisága alapján kell kiválasztania.

Csoportosított kapcsolatok

A HttpClient kapcsolatkészlet az alapul szolgáló SocketsHttpHandler-hez van csatolva. Amikor a HttpClient példány megsemmisül, a készletben található összes meglévő kapcsolatot is megsemmisíti. Ha később ugyanahhoz a kiszolgálóhoz küld egy kérelmet, új kapcsolatot kell létrehozni. Ennek eredményeképpen teljesítménybeli büntetés jár a szükségtelen kapcsolatlétrehozásért. Ezenkívül a TCP-portok nem lesznek azonnal felszabadítva a kapcsolat bezárása után. (Erről további információt az RFC 9293 TCP-ben TIME-WAITtalál.) Ha a kérelmek száma magas, az elérhető portok operációsrendszer-korlátja kimerülhet. A portkimerülési problémák elkerülése érdekében javasoljuk, hogy a lehető legtöbb HTTP-kéréshez használjon HttpClient újra példányokat.

Az élettartam-kezelés szempontjából javasolt HttpClient használat összegzéséhez vagy hosszú élettartamú ügyfeleket kell használni és beállítani PooledConnectionLifetime (.NET Core és .NET 5+), vagy pedig a által létrehozott IHttpClientFactory ügyfeleket.

  • A .NET Core-ban és a .NET 5+-ban:

    • A várt DNS-változásoktól függően használjon egy static vagy egypéldányosHttpClient példányt, amelyet PooledConnectionLifetime a kívánt időköz, például 2 perc, szerint állított be. Ez a portkimerüléssel és a DNS-módosításokkal kapcsolatos problémákat is megoldja anélkül, hogy hozzáadja a terhelést.IHttpClientFactory Ha képesnek kell lennie immitálni a kezelőt, külön regisztrálhatja.

    Tipp.

    Ha csak korlátozott számú HttpClient példányt használ, az is elfogadható stratégia. A lényeg az, hogy nincsenek létrehozva és törölve minden egyes kérésnél, mivel mindegyik tartalmaz egy kapcsolatkészletet. Több példány használata több proxyval rendelkező forgatókönyvekhez vagy a cookie-tárolók elkülönítéséhez szükséges anélkül, hogy teljesen letiltanák a cookie-k kezelését.

    • A IHttpClientFactory használatával több, eltérően konfigurált ügyfél is rendelkezésre állhat a különböző használati esetekhez. Vegye azonban figyelembe, hogy a gyári ügyfelek rövid élettartamúak, és az ügyfél létrehozása után a gyár már nem rendelkezik felette.

      A gyár készletezi a HttpMessageHandler példányokat, és ha az élettartamuk nem járt le, egy kezelő újra felhasználható a készletből, amikor a gyár egy új HttpClient példányt hoz létre. Ez az újrahasználat elkerüli a socket kimerülési problémáit.

      Ha szeretné kihasználni a IHttpClientFactory által nyújtott konfigurálhatóságot, javasoljuk a típusos kliens megközelítést használni.

  • A .NET-keretrendszerben használja a IHttpClientFactory a HttpClient példányok kezelésére. Ha nem használja a gyárat, és ehelyett saját maga hoz létre egy új ügyfélpéldányt az egyes kérésekhez, kimerítheti az elérhető portokat.

    Figyelmeztetés

    Ha az alkalmazás cookie-kat igényel, javasoljuk, hogy kerülje a használatot IHttpClientFactory. Az HttpMessageHandler példányok összesítése az CookieContainer objektumok megosztását eredményezi. A nem várt CookieContainer megosztás cookie-kat szivárogtathat ki az alkalmazás nem kapcsolódó részei között. Továbbá, ha HandlerLifetime lejár, a kezelő újrahasznosításra kerül, ami azt jelenti, hogy a CookieContainer-ben tárolt összes cookie elveszik.

Az élettartam kezelésével HttpClientIHttpClientFactorykapcsolatos további információkért tekintse meg azIHttpClientFactoryirányelveket.

Rugalmasság statikus ügyfelekkel

Az alábbi minta használatával konfigurálhat egy static vagy szingelton ügyfélt tetszőleges számú rugalmassági folyamat használatára:

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

A fenti kód a következőket végzi el:

  • A Microsoft.Extensions.Http.Resilience NuGet-csomagra támaszkodik.
  • Egy átmeneti HTTP-hibakezelőt ad meg, amely újrapróbálkozási folyamattal van konfigurálva, amely minden kísérlet esetén exponenciálisan késlelteti a késleltetési időközöket.
  • A socketHandler készletezett kapcsolatának élettartama tizenöt percig tart.
  • Átadja a socketHandler-t a resilienceHandler-nek az újrapróbálkozási logikával.
  • Példányosít egy megosztott HttpClient a resilienceHandleralapján.

Lásd még