System.Net.Http.HttpClient 類別
本文提供此 API 參考文件的補充備註。
HttpClient類別執行個體是做為工作階段使用以傳送 HTTP 要求。 HttpClient執行個體是套用至該執行個體所執行之所有要求的設定集合。 此外,每個 HttpClient執行個體都使用自己的連接集區,這樣可將其要求與由其他 HttpClient 執行個體執行的要求隔離。
執行個體
HttpClient 旨在具現化一次,並在整個應用程式的生命週期中重複使用。 在 .NET Core 和 .NET 5+中,HttpClient 集區處理程序實例內的連線,並重複使用跨多個要求之間的連線。 如果您為每個要求具現化 HttpClient 類別,將會耗盡大量負載下可用的套接字數目。 此耗盡會導致 SocketException 錯誤。
您可以藉由傳入 「處理程式」來設定其他選項,例如 HttpClientHandler (或 SocketsHttpHandler .NET Core 2.1 或更新版本中),做為建構函式的一部分。 提交要求之後,處理程式上的連接屬性就無法變更,因此如果您需要變更連接屬性,建立新的 HttpClient 實例的原因之一就是。 如果不同的要求需要不同的設定,這也可能會導致應用程式有多個 HttpClient 實例,其中每個實例都已適當地設定,然後在相關的用戶端上發出要求。
HttpClient 只會在建立連線時解析 DNS 專案。 它不會追蹤 DNS 伺服器所指定的任何存留時間 (TTL) 長度。 如果 DNS 專案定期變更,這可能會在某些容器案例中發生,則用戶端不會遵守這些更新。 若要解決此問題,您可以藉由設定 SocketsHttpHandler.PooledConnectionLifetime 屬性來限制連線的存留期,以便在取代連線時需要 DNS 查閱。
public class GoodController : ApiController
{
private static readonly HttpClient httpClient;
static GoodController()
{
var socketsHandler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(2)
};
httpClient = new HttpClient(socketsHandler);
}
}
除了只建立一個 HttpClient 實例,您也可以使用 IHttpClientFactory 來管理 HttpClient 實例。 如需詳細資訊,請參閱使用 HttpClient 的指導方針。
衍生
HttpClient也會做為更特定 HTTP 用戶端的基類。 例如,FacebookHttpClient 會提供 Facebook Web 服務特定的其他方法(例如 GetFriends
方法)。 衍生類別不應覆寫 類別上的虛擬方法。 請改用接受 HttpMessageHandler 的建構函式多載來設定任何預先要求或要求后處理。
傳輸
HttpClient是一個高階 API,會包裝其執行所在每個平臺上可用的較低層級功能。
在每個平臺上, HttpClient 嘗試使用最佳的可用傳輸:
主機/運行時間 | 後端 |
---|---|
Windows/.NET Framework | HttpWebRequest |
Windows/Mono | HttpWebRequest |
Windows/UWP | Windows 原生 WinHttpHandler (HTTP 2.0 支援) |
Windows/.NET Core 1.0-2.0 | Windows 原生 WinHttpHandler (HTTP 2.0 支援) |
Android/Xamarin | 在建置階段選取。 HttpWebRequest可以使用 或 設定為使用Android的原生HttpURLConnection |
iOS, tvOS, watchOS/Xamarin | 在建置階段選取。 HttpWebRequest可以使用 或 設定為使用 Apple 的 NSUrlSession (HTTP 2.0 支援) |
macOS/Xamarin | 在建置階段選取。 HttpWebRequest可以使用 或 設定為使用 Apple 的 NSUrlSession (HTTP 2.0 支援) |
macOS/Mono | HttpWebRequest |
macOS/.NET Core 1.0-2.0 | libcurl 型 HTTP 傳輸 (支援 HTTP 2.0) |
Linux/Mono | HttpWebRequest |
Linux/.NET Core 1.0-2.0 | libcurl 型 HTTP 傳輸 (支援 HTTP 2.0) |
.NET Core 2.1 和更新版本 | System.Net.Http.SocketsHttpHandler |
使用者也可以叫用採用 HttpMessageHandler的建構函式來HttpClient設定 的特定傳輸HttpClient。
.NET Framework 和 Mono
根據預設, HttpWebRequest .NET Framework 和 Mono 會用來將要求傳送至伺服器。 藉由使用 參數指定其中一個建構函式多載 HttpMessageHandler 中的不同處理程式,即可修改此行為。 如果您需要驗證或快取等功能,您可以使用 WebRequestHandler 來設定設定,並將實例傳遞至建構函式。 傳回的處理程式可以傳遞至具有 參數的 HttpMessageHandler 建構函式多載。
.NET Core
從 .NET Core 2.1 開始,類別 System.Net.Http.SocketsHttpHandler 會 HttpClientHandler 提供較高層級 HTTP 網路類別所使用的實作,例如 HttpClient。 使用 SocketsHttpHandler 提供許多優點:
- 與之前的實作相比,能提供顯著的效能提升。
- 消除平臺相依性,可簡化部署和服務。 例如,
libcurl
不再相依於macOS的 .NET Core 和適用於Linux的 .NET Core。 - 所有 .NET 平臺的一致行為。
如果這項變更不理想,您可以在 Windows 上繼續使用 WinHttpHandler ,方法是參考其 NuGet 套件 ,並手動將它傳遞至 HttpClient 的建構函式 。
使用運行時間組態選項設定行為
某些方面 HttpClient的行為可透過 運行時間組態選項來自定義。 不過,這些參數的行為與 .NET 版本不同。 例如,在 .NET Core 2.1 - 3.1 中,您可以設定是否 SocketsHttpHandler 預設使用 ,但從 .NET 5 開始,就無法再使用該選項。
連線共用
HttpClient 會盡可能集區 HTTP 連線,並將它們用於多個要求。 這有顯著的效能優點,尤其是 HTTPS 要求,因為連線交握只會完成一次。
連線 集區屬性可以在 建構期間設定HttpClientHandler或SocketsHttpHandler傳入,包括 MaxConnectionsPerServer、 PooledConnectionIdleTimeout和 PooledConnectionLifetime。
處置 HttpClient 實例會關閉開啟的連接,並取消任何擱置的要求。
注意
如果您同時將 HTTP/1.1 要求傳送至相同的伺服器,則可以建立新的連線。 即使您重複使用 HttpClient
實例,如果要求速率很高,或有任何防火牆限制,可能會因為預設 TCP 清除定時器而耗盡可用的套接字。 若要限制並行連線數目,您可以設定 MaxConnectionsPerServer
屬性。 根據預設,並行 HTTP/1.1 連線的數目不受限制。
緩衝處理和要求存留期
根據預設,HttpClient 方法 (except GetStreamAsync) 會緩衝來自伺服器的回應,先將所有回應本文讀入記憶體,再傳回異步結果。 這些要求會繼續執行,直到發生下列其中一項:
- 成功 Task<TResult> 並傳回結果。
- 到達 Timeout 時, Task<TResult> 將會取消 。
- 會 CancellationToken 引發可傳遞至某些方法多載的 。
- 呼叫 CancelPendingRequests()。
- HttpClient 已處置。
您可以使用某些方法多載可用的參數,根據 HttpCompletionOption 每個要求變更緩衝行為。 這個自變數可用來指定在唯讀取回應標頭之後,或讀取和緩衝響應內容之後,是否 Task<TResult> 應該視為完成。
如果您的應用程式在 HttpClient 命名空間中使用 System.Net.Http 和相關類別想要下載大量數據(50 MB 以上),則應用程式應該串流這些下載,而不使用預設的緩衝處理。 如果您使用默認緩衝處理,則用戶端記憶體使用量會變得非常大,可能會導致大幅降低效能。
執行緒安全
下列方法是安全線程:
- CancelPendingRequests
- DeleteAsync
- GetAsync
- GetByteArrayAsync
- GetStreamAsync
- GetStringAsync
- PostAsync
- PutAsync
- SendAsync
Proxy
根據預設,根據平臺,HttpClient 會從環境變數或使用者/系統設定讀取 Proxy 組態。 您可以依照優先順序將 或 IWebProxy 傳遞WebProxy至 來變更此行為:
- Proxy HttpClientHandler 在 HttpClient 建構期間傳入的屬性
- DefaultProxy靜態屬性 (影響所有實例)
您可以使用 停用 Proxy UseProxy。 Windows 使用者的預設組態是嘗試並偵測使用網路探索的 Proxy,這可能會變慢。 對於已知不需要 Proxy 的高輸送量應用程式,您應該停用 Proxy。
只有在使用 HttpClient 提出第一個要求之前,才應該變更 Proxy 設定(例如 Credentials)。 第一次使用 HttpClient 之後所做的變更可能不會反映在後續要求中。
逾時
您可以使用 Timeout 來設定來自 HttpClient 實例之所有 HTTP 要求的預設逾時。 逾時僅適用於導致起始要求/回應的 xxxAsync 方法。 如果達到逾時, Task<TResult> 則會取消該要求的 。
如果您在建構 HttpClient 物件時傳入 SocketsHttpHandler 實體,可以設定一些額外的逾時:
屬性 | 說明 |
---|---|
ConnectTimeout | 指定要求需要建立新的 TCP 連線時所使用的逾時。 如果發生逾時,則會取消要求 Task<TResult> 。 |
PooledConnectionLifetime | 指定要用於連接集區中每個連線的逾時。 如果連線處於閑置狀態,則會立即關閉連線;否則,連接會在目前要求的結尾關閉。 |
PooledConnectionIdleTimeout | 如果連線集區中的連線長時間閑置,連線就會關閉。 |
Expect100ContinueTimeout | 如果要求有「預期:100-continue」標頭,則會延遲傳送內容直到逾時或收到「100-continue」回應為止。 |
HttpClient 只會在建立連線時解析 DNS 專案。 它不會追蹤 DNS 伺服器所指定的任何存留時間 (TTL) 長度。 如果 DNS 專案經常變更,在某些情況下可能會發生這種情況,您可以使用 PooledConnectionLifetime 來限制連線的存留期,以便在取代連線時需要 DNS 查閱。