共用方式為


HttpClient 使用方針

System.Net.Http.HttpClient 類型傳送 HTTP 要求並從由 URI 識別之資源接收 HTTP 回應。 HttpClient 執行個體是套用至該執行個體執行的所有請求的設定集合,每個執行個體都使用自己的連線集區,將自己的請求與其他請求隔離開來。 從 .NET Core 2.1 開始,SocketsHttpHandler 類別會提供實作,讓所有平台的行為保持一致。

DNS 行為模式

HttpClient 僅會在連線建立後,解析 DNS 項目。 它不會追蹤 DNS 伺服器所指定的任何存留時間 (TTL) 長度。 如果 DNS 項目定期變更 (在某些情況下可能會發生),用戶端將不會遵守這些更新。 若要解決此問題,您可以透過設定 PooledConnectionLifetime 屬性,限制連線的存留期,以便在替代連線時重複 DNS 查閱。 請考慮下列範例:

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

上述 HttpClient 會設定為重複使用連線 15 分鐘。 在經過 PooledConnectionLifetime 指定的時間範圍並且連線已完成其最後一個相關聯要求 (如果有的話) 之後,此連線便會關閉。 如果佇列中有任何要求正在等待,則會視需要建立新的連線。

為了方便說明,會任意選擇 15 分鐘的間隔。 您應該依據 DNS 或其他網路變更的預期頻率來選擇值。

集區式連線

HttpClient 的連線集區會連結至基礎 SocketsHttpHandler。 當 HttpClient 執行個體被處置時,會連帶處置集區內所有現有的連線。 如果您稍後將要求傳送至相同的伺服器,則必須重新建立新的連線。 因此,不必要的連線建立會產生效能損失。 此外,連線關閉之後,不會立即釋放 TCP 連接埠。 (如需詳細資訊,請參閱 TIME-WAIT 中的 TCP 。)如果要求率很高,則可能會耗盡作業系統的可用連接埠。 若要避免連接埠耗盡問題,建議您盡可能對多個 HTTP 要求重複使用 HttpClient 執行個體。

為了概述存留期管理方面的建議 HttpClient 使用方式,您應該使用由 建立的長存期客戶端並設定 PooledConnectionLifetime (.NET Core 和 .NET 5+) 或使用由 建立的短存期客戶端 IHttpClientFactory

  • 在 .NET Core 和 .NET 5+:

    • 根據預期的 DNS 變更,使用 static單例HttpClient 實例,並將 PooledConnectionLifetime 設定為所需的間隔,例如 2 分鐘。 這可解決連接埠耗盡和 DNS 變更問題,而不會增加 IHttpClientFactory 的額外負荷。 如果您需要模擬處理常式,可以將其單獨註冊。

    小技巧

    如果您只使用有限的 HttpClient 實例數目,這也是可接受的方法。 重點在於,這些執行個體不會隨著每個要求而被建立及處置,因為它們各自包含連線集區。 在需要使用多個 Proxy 的情境中,或是想要分隔 Cookie 容器而不完全停用 Cookie 處理時,必須使用多個執行個體。

    • 您可以使用 IHttpClientFactory,為不同使用案例設定多個配置不同的用戶端。 不過,請注意,工廠創建的客戶端是短暫存在的,而且一旦客戶端創建後,工廠將無法再控制它。

      處理站集區 HttpMessageHandler 執行個體,如果其存留期尚未過期,當處理站建立新的 HttpClient 執行個體時,可以從集區重複使用處理程式。 此重複使用可避免任何通訊端耗盡問題。

      如果您希望擁有 IHttpClientFactory 提供的可設定性,我們建議您使用型別化客戶端方法

  • 在 .NET Framework 中,使用 IHttpClientFactory 來管理您的 HttpClient 執行個體。 如果您不使用工廠方法,而是自行為每個請求建立新的客戶端實例,則可能會耗盡可用的連接埠。

    警告

    如果您的應用程式需要 Cookie,建議您避免使用 IHttpClientFactory。 將 HttpMessageHandler 執行個體合併後,會共用 CookieContainer 物件。 非預期的 CookieContainer 共用可能會洩漏應用程式不相關部分之間的Cookie。 此外,當 HandlerLifetime 到期時,處理程式會被回收利用,這表示儲存在其 HandlerLifetime 中的所有 Cookie 都會遺失。

如需使用 HttpClient 管理 IHttpClientFactory 存留期的詳細資訊,請參閱 IHttpClientFactory 指導方針

靜態客戶端的復原力

您可以使用下列模式,將static單例用戶端設定為可使用任意數量的復原管線:

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

上述 程式碼:

  • 依賴 Microsoft.Extensions.Http.Resilience NuGet 套件。
  • 指定暫時性 HTTP 錯誤處理常式,並使用設定的重試機制,每次嘗試都會以指數方式增加延遲時間。
  • 定義的 socketHandler 集區連線存留期為15分鐘。
  • 使用重試邏輯將 socketHandler 傳遞至 resilienceHandler
  • 具現化一個共用的 HttpClient,給定 resilienceHandler

另請參閱