共用方式為


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 連接埠。 (如需詳細資訊,請參閱 RFC 9293 中的 TCP TIME-WAIT。)如果要求率很高,則可能會耗盡作業系統的可用連接埠。 若要避免連接埠耗盡問題,建議您盡可能對多個 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,請考慮停用自動 Cookie 處理或避免 IHttpClientFactory。 將 HttpMessageHandler 執行個體合併後,會共用 CookieContainer 物件。 未預期的 CookieContainer 物件共用通常會導致程式碼不正確。

如需使用 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

重要

Microsoft.Extensions.Http.Resilience 程式庫目前標示為 實驗性,未來可能會變更。

另請參閱