共用方式為


System.Net.Http.HttpClient 類別

本文提供此 API 參考文件的補充備註。

類別 HttpClient 實例可作為傳送 HTTP 要求的會話。 HttpClient實例是套用至該實例所執行之所有要求的設定集合。 此外,每個實例都會HttpClient使用自己的連接池,將其要求與其他實例HttpClient執行的要求隔離開來。

實體化

HttpClient 旨在具現化一次,並在整個應用程式的生命週期中重複使用。 在 .NET Core 和 .NET 5+ 中,HttpClient 在處理程序實例內管理連線,並在多個要求間重複使用同一連線。 如果您為每個請求實例化 HttpClient 類,在高負載情況下,會耗盡可用的套接字數量。 此耗盡會導致 SocketException 錯誤。

您可以透過傳入「處理程式」來配置其他選項,例如 HttpClientHandler (或在 .NET Core 2.1 或更高版本中使用 SocketsHttpHandler),作為建構函式的一部分。 提交要求之後,處理程式上的連接屬性就無法變更,因此如果您需要變更連接屬性,建立新的 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 支援)
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

使用者也可以通過叫用採用 HttpClientHttpClient建構函式來配置 HttpMessageHandler 的特定傳輸。

.NET Framework 和 Mono

根據預設, HttpWebRequest .NET Framework 和 Mono 會用來將要求傳送至伺服器。 要修改此行為,可在其中一個具有 HttpMessageHandler 參數的建構函式多載中指定不同的處理程式。 如果您需要驗證或快取等功能,您可以使用 WebRequestHandler 來設定設定,並將實例傳遞至建構函式。 傳回的處理程式可以傳遞至具有 HttpMessageHandler 參數的建構函式多載。

.NET 核心

從 .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 請求來說,因為連線的握手只需進行一次。

連接集區屬性可以在建構過程中通過HttpClientHandlerSocketsHttpHandler來配置,包括MaxConnectionsPerServerPooledConnectionIdleTimeoutPooledConnectionLifetime

釋放 HttpClient 實例會關閉開啟的連接,並取消任何擱置的請求。

備註

如果您同時將 HTTP/1.1 要求傳送至相同的伺服器,則可以建立新的連線。 即使您重複使用 HttpClient 實例,但如果請求率很高或存在任何防火牆限制,由於預設的 TCP 清理計時器,這可能會耗盡可用的套接字。 若要限制並行連線數目,您可以設定 MaxConnectionsPerServer 屬性。 根據預設,並行 HTTP/1.1 連線的數目不受限制。

緩衝處理和請求壽命

根據預設,HttpClient 方法 (except GetStreamAsync) 會緩衝來自伺服器的回應,先將所有回應本文讀入記憶體,再傳回異步結果。 這些請求會持續進行,直到發生下列其中一項:

您可以使用某些方法重載中可用的HttpCompletionOption參數,根據每個請求變更緩衝行為。 這個參數可以用來指定僅讀取回應標頭後,或在讀取和緩衝回應內容後,是否應將 Task<TResult> 視為完成。

如果您的應用程式在 HttpClient 命名空間中使用 System.Net.Http 和相關類別想要下載大量數據(50 MB 以上),則應用程式應該串流這些下載,而不使用預設的緩衝處理。 如果您使用默認緩衝處理,則用戶端記憶體使用量會變得非常大,可能會導致大幅降低效能。

執行緒安全

下列方法是執行緒安全:

Proxy

根據預設,根據平臺,HttpClient 會從環境變數或使用者/系統設定讀取 Proxy 組態。 您可以通過依優先順序傳遞WebProxyIWebProxy來變更此行為。

  • 在 HttpClient 建構期間傳入的 HttpClientHandler 的 Proxy 屬性
  • DefaultProxy靜態屬性 (影響所有實例)

您可以關閉代理 UseProxy。 Windows 使用者的預設組態是藉由網路探索來偵測 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 查詢。