.NET Core中HttpClient的正確打開(kāi)方式
前言
在 Asp.Net Core 1.0 時(shí)代,由于設(shè)計(jì)上的問(wèn)題, HttpClient 給開(kāi)發(fā)者帶來(lái)了無(wú)盡的困擾,用 Asp.Net Core
開(kāi)發(fā)團(tuán)隊(duì)的話來(lái)說(shuō)就是:我們注意到,HttpClient 被很多開(kāi)發(fā)人員不正確的使用。得益于 .Net Core
不斷的版本快速升級(jí);
問(wèn)題來(lái)源
長(zhǎng)期以來(lái),.NET開(kāi)發(fā)者都通過(guò)下面的方式發(fā)送http請(qǐng)求:
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(uri);
//do something with response
}
這段代碼理論上來(lái)說(shuō)遵守了C#的最佳實(shí)踐,HttpClient是IDisposable類型,所以我們通過(guò)using語(yǔ)法糖來(lái)使用HttpClient。微軟官方的文檔也提到:
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement
可是,當(dāng)我們?cè)噲D運(yùn)行下面的測(cè)試:
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");
}
此時(shí)在terminal下列出所有端口:
netstat -ap tcp | grep -i "time_wait"

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

