System.Net.Http.HttpClient 類用於發送 HTTP 請求以及從 URI 所標識的資源接收 HTTP 響應。 HttpClient 實例是應用於該實例執行的所有請求的設置集合,每個實例使用自身的連接池,該池將其請求與其他請求隔離開來。 從 .NET Core 2.1 開始,SocketsHttpHandler 類提供實現,使行爲在所有平臺上保持一致。
HttpClient實例是執行網絡請求的設置集合,每個實例會使用一個連接池。通過這段描述我們知道實際使用HttpClient的時候我們只需要實例化一個就行了,在處理程序實例內池連接,並在多個請求之間重複使用連接。也就是官方提倡的使用單個實例,如果每次請求就實例化一個HttpClient,則會創建不必要的連接降低性能,並且TCP 端口不會在連接關閉後立即釋放。
所以如果是大批量創建HttpClient請求則大量負載下可用的套接字數將耗盡,這種耗盡將導致 SocketException 錯誤。
使用方式
- 使用靜態變量。
static readonly HttpClient httpClient = new HttpClient();
- 使用單例模式
public class HttpClientInstance
{
private static readonly HttpClient _HttpClient;
static HttpClientInstance()
{
_HttpClient = new HttpClient();
}
public static HttpClient GetHttpClient()
{
return _HttpClient;
}
}
實例化參數
可以通過構造參數(如 HttpClientHandler (或 SocketsHttpHandler .NET Core 2.1 或更高版本) )作爲構造函數的一部分來配置其他選項。 實例化HttpClient後無法更連接屬性,因此,如果需要更改連接屬性,則需要創建新的 HttpClient 實例。
配置可以在構造期間配置 HttpClientHandler 或 SocketsHttpHandler 傳入,SocketsHttpHandler可以設置額外參數包括 MaxConnectionsPerServer, PooledConnectionIdleTimeout、PooledConnectionLifetime、ConnectTimeout。
- MaxConnectionsPerServer:HttpClient 對象所允許的最大併發連接數。
- PooledConnectionIdleTimeout: PooledConnectionLifetime 指定的時間範圍過後,系統會關閉連接,然後創建一個新連接。
- PooledConnectionLifetime:指定要用於連接池中每個連接的超時值。 如果連接處於空閒狀態,則連接會立即關閉;否則,連接在當前請求結束時關閉。
- ConnectTimeout:指定在請求需要創建新的 TCP 連接時使用的超時。 如果發生超時,將取消請求 Task
。
var handler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15)
};
var httpClient = new HttpClient(handler);
在.NET Framework 只能使用HttpClientHandler
,且沒有PooledConnectionIdleTimeout和PooledConnectionLifetime等參數。
HttpClientHandler httpClientHandler = new HttpClientHandler();
//最大併發連接數
httpClientHandler.MaxConnectionsPerServer = 100;
HttpClient httpClient=new HttpClient(httpClientHandler);
//超時設置
httpClient.Timeout = new TimeSpan(5000);
可以是設置MaxConnectionsPerServer,可以設置Timeout
。Timeout 爲來自 HttpClient 實例的所有 HTTP 請求設置默認超時。 超時僅適用於導致啓動請求/響應的 xxxAsync 方法。 如果達到超時,則會 Task
請求實現
HttpClient這是一個高級 API,用於包裝其運行的每個平臺上可用的較低級別功能。
在每個平臺上, HttpClient 嘗試使用最佳可用傳輸:
注意事項
在上面實現可以看到在不同的框架下HttpClient的實現是不一樣的,在.NET Framework下是使用HttpWebRequest
支持。
所以還會受限HttpWebRequest的實現,如果我們要啓用多線程高頻率調用接口,那麼這裏要注意HttpWebRequest的連接併發的數量限制。HttpWebRequest通過ServicePoint設置,我們通過反編譯看到HttpWebRequest構造函數。
ServicePoint.DefaultConnectionLimit獲取允許的最大併發連接數。 對於 ASP.NET 託管的應用程序,默認連接限制爲 10,對於所有其他應用程序,默認連接限制爲 2。DefaultConnectionLimit 對現有 ServicePoint 對象沒有影響;它隻影響更改後初始化的對象。如果未直接或通過配置設置此屬性的值,則該值默認爲常量 DefaultPersistentConnectionLimit
。
如果是應用連接池默認只有2個併發,所以當你啓用很多線程的時候實際效率是不會提升的,一直只有兩個併發在阻塞排隊,如果請求比較耗時後面的請求還有異常的可能。
因此當你使用多線程的時候要注意初始化HttpClient的httpClientHandler.MaxConnectionsPerServer = n;
該參數用於設置。
RestSharp
平時我們可能使用RestSharp 用於網絡請求,實際也是在HttpWebRequest上的封裝,在官網我們可以看到如下說明:
在最新的v107換成了HttpClient,以前的版本也是HttpWebRequest。如果要設置RestSharp的連接池併發數需要修改默認值。
System.Net.ServicePointManager.DefaultConnectionLimit = n;
然後再實例化RestClient。