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 提供的可設定性,我們建議您使用型別化客戶端方法。
- 根據預期的 DNS 變更,使用
在 .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
。