.NET Core中HttpClient的正確打開方式
前言
在 Asp.Net Core 1.0 時代,由于設(shè)計上的問題, HttpClient 給開發(fā)者帶來了無盡的困擾,用 Asp.Net Core
開發(fā)團隊的話來說就是:我們注意到,HttpClient 被很多開發(fā)人員不正確的使用。得益于 .Net Core
不斷的版本快速升級;
問題來源
長期以來,.NET開發(fā)者都通過下面的方式發(fā)送http請求:
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(uri);
//do something with response
}
這段代碼理論上來說遵守了C#的最佳實踐,HttpClient是IDisposable類型,所以我們通過using語法糖來使用HttpClient。微軟官方的文檔也提到:
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement
可是,當(dāng)我們試圖運行下面的測試:
public async Task SendRequest()
{
Console.WriteLine("Starting reqeust");
for(int i = 0; i<10; i++)
{
using(var client = new HttpClient())
{
var result = await client.GetAsync("http://www.baidu.com");
Console.WriteLine(result.StatusCode);
}
}
Console.WriteLine("Reqeust done");
}
此時在terminal下列出所有端口:
netstat -ap tcp | grep -i "time_wait"

你會發(fā)現(xiàn)本地開啟了10個端口,這說明HttpClient的工作原理其實跟我們認(rèn)為的IDisposable是有區(qū)別的,如果你把HttpClient用作大規(guī)模的Http請求,實際上會創(chuàng)建很多個Http連接,而且這些資源并不能被立即釋放。一個顯而易見的改進(jìn)方法是共享同一個HttpClient實例,從而達(dá)到節(jié)約socket資源的目的。
private static readonly HttpClient _client = new HttpClient();
public async Task SendRequest2()
{
_testOutputHelper.WriteLine("Start request");
for(int i = 0; i<10; i++)
{
var result = await _client.GetAsync("http://www.baidu.com");
Console.WriteLine(result.StatusCode);
}
_testOutputHelper.WriteLine("Request done");
}
這個方案似乎解決了問題,使用單例的HttpClient的確會減少Socket資源,但是這個方案會引發(fā)新的問題:由于這個Http連接始終保持連接狀態(tài),所以當(dāng)請求地址的DNS發(fā)生更新的時候并不會應(yīng)用到這個Http連接上。這個問題在微服務(wù),高可用時代更加常見Singeton HttpClient doesn't respect DNS changes。
最終,一個叫做HttpClientFactory的開源實現(xiàn)用來徹底解決這個問題。微軟也將HttpClientFactory集成在了.NET Core中。
在.NET Core中創(chuàng)建HttpClient
1.添加Nuget
Microsoft.Extensions.Http
2.在Dependency Injection容器中注冊服務(wù)
services.AddHttpClient();
3. 使用構(gòu)造器注入使用IhttpClientFactory
public class BasicUsage
{
private readonly IHttpClientFactory _clientFactory;
public BasicUsage(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task SendRequest()
{
var request = new HttpRequestMessage(HttpMethod.Get,
"http://www.baidu.com");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);
//do something for response
}
}
4. 使用Named HttpClient
由于我們在DI容器中注冊了唯一的HttpClientFactory,意味著通過HttpClientFactory創(chuàng)建出來的HttpClient可能是同一個配置和參數(shù),如果你需要不同配置的HttpClient,你可以通過“起名字的”的方式注冊不同的HttpClient。
services.AddHttpClient("baidu", c =>
{
c.BaseAddress = new Uri("https://www.baidu.com");
c.DefaultRequestHeaders.Add("Accept", "application/json");
});
一旦注冊了一個名叫“baidu"的HttpClient,你就可以通過下面的方式來建創(chuàng)建HttpClient:
var client = _clientFactory.CreateClient("baidu");
5.集成Polly
Polly是一個用來故障處理庫,它允許開發(fā)者在Http請求中添加“重試、熔斷器、超時等”策略。
先添加Nuget:
Microsoft.Extensions.Http.Polly
添加策略:
var timeout = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(10));
services.AddHttpClient("baidu")
.AddPolicyHandler(request => timeout)
.AddTransientHttpErrorPolicy(p=>p.RetryAsync(3));
當(dāng)然還有一些高階用法,詳見Initiate HTTP requests,總之HttpClientFactory提供了一種高效實用HttpClient的方式,如果你還在自己new HttpClient,請趕快試試新的方案吧。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- ASP.NET Core 文件響應(yīng)壓縮的常見使用誤區(qū)
- ASP.NET Core中的響應(yīng)壓縮的實現(xiàn)
- asp.net core為IHttpClientFactory添加動態(tài)命名配置
- 如何在ASP.NET Core中使用HttpClientFactory
- 在ASP.NET Core中用HttpClient發(fā)送POST, PUT和DELETE請求
- .NET CORE HttpClient的使用方法
- .NET Core使用HttpClient進(jìn)行表單提交時遇到的問題
- .Net Core下HTTP請求IHttpClientFactory示例詳解
- Asp.Net Core2.1前后使用HttpClient的兩種方式
- ASP.NET Core針對一個使用HttpClient對象的類編寫單元測試詳解
- .NET Core中使用HttpClient的正確姿勢
- .NET Core 2.1中HttpClientFactory的最佳實踐記錄
- .Net Core HttpClient處理響應(yīng)壓縮詳細(xì)
相關(guān)文章
Global.asax的Application_Error實現(xiàn)錯誤記錄/錯誤日志的代碼
本文為大家介紹下利用Global.asax的Application_Error實現(xiàn)錯誤記錄,具體如下,有此需求的朋友可以參考下,希望對大家有所幫助2013-08-08
ASP.Net中數(shù)據(jù)展示控件的嵌套使用示例
ASP.Net中數(shù)據(jù)展示控件的嵌套使用,在Repeater里面嵌套一個GridView,將每個User的任務(wù)展示出來2014-09-09
詳解ASP.NET Core 中的多語言支持(Localization)
本篇文章主要介紹了ASP.NET Core 中的多語言支持(Localization) ,具有一定的參考價值,有興趣的可以了解一下2017-08-08
ASP.NET將Session保存到數(shù)據(jù)庫中的方法
因為ASP.NET中Session的存取機制與ASP相同,都是保存在進(jìn)行中, 一旦進(jìn)程崩潰,所有Session信息將會丟失,所以我采取了將Session信息保存到SQL Server中,盡管還有其它的2013-08-08
asp.net使用Repeater控件中的全選進(jìn)行批量操作實例
這篇文章主要介紹了asp.net使用Repeater控件中的全選進(jìn)行批量操作方法,實例分析了Repeater控件的使用技巧,需要的朋友可以參考下2015-01-01
微信公眾平臺開發(fā)教程(二) 基本原理及消息接口總結(jié)
本篇文章主要介紹了微信公眾平臺開發(fā)教程(二) 基本原理及消息接口,具有一定的參考價值,有興趣的朋友可以了解一下。2016-12-12
ASP.NET?Core項目使用xUnit進(jìn)行單元測試
這篇文章介紹了ASP.NET?Core項目使用xUnit進(jìn)行單元測試的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03
.NET6+Quartz實現(xiàn)定時任務(wù)的示例詳解
在實際工作中,經(jīng)常會有一些需要定時操作的業(yè)務(wù),如:定時發(fā)郵件,定時統(tǒng)計信息等,那么如何實現(xiàn)才能使得我們的項目整齊劃一呢?本文通過一些簡單的小例子,簡述在.Net6+Quartz實現(xiàn)定時任務(wù)的一些基本操作,如有不足之處,還請指正2023-03-03
使用最小?WEB?API?實現(xiàn)文件上傳的Swagger支持
這篇文章主要介紹了使用最小?WEB?API?實現(xiàn)文件上傳Swagger支持,我們使用最小?WEB?API?實現(xiàn)文件上傳功能,雖然客戶端訪問是正常的,但是當(dāng)打開?Swagger?頁面時,沒法使用?Swagger?頁面測試,下面就來一篇支持Swagger的,需要的小伙伴可以參考一下2022-02-02
3分鐘快速學(xué)會在ASP.NET Core MVC中如何使用Cookie
這篇文章主要給大家介紹了關(guān)于如何通過3分鐘快速學(xué)會在ASP.NET Core MVC中使用Cookie的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用ASP.NET具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12

