ASP.NET Core中HttpClient的使用方式

2019 年 3 月 1 日 DotNet

(给DotNet加星标,提升.Net技能


转自:微笑刺客D

cnblogs.com/CKExp/p/10426170.html


在.NET Core应用开发中,调用第三方接口也是常有的事情,HttpClient使用人数、使用频率算是最高的一种了,在.NET Core中,HttpClient的使用方式随着版本的升级也发生了一些变化,本次就讲解一下ASP.NET Core 2.1前后使用的两种方式。


一、原先HttpClient使用方式


一般来讲,喜欢要用的时候才会选择去获取资源,因此,当在有需求时才会用HttpClient去调用资源,便会使用如下这种方式或其它方式获取资源。


//do something...using (var httpClient = new HttpClient()){    var requestUri = "http://aspnetcore.online/api/resource/getresource";    var httpResponseMessage = await httpClient.GetAsync(requestUri);    //do something...    return Ok(httpResponseMessage);}


如果可以正常访问目标地址的话,则会返回相应的资源信息。



又如Post方式提交并返回相应的内容,都是可以直接使用。


//do something...using (var httpClient = new HttpClient()){    var requestUri = "http://aspnetcore.online/api/resource/postresource";    var httpResponseMessage = await httpClient.PostAsJsonAsync(requestUri,"星城软件");    //do something...    return Ok(httpResponseMessage);}


但是这种情况下会出现一个严重的问题,在不停的调用情形下,tcp连接数会被耗尽,虽然使用using方式调用HttpClient并在退出前调用Dispose()方法将HttpClient释放了,但是tcp连接仍然处于保持状态,在240s后才会自动断开,这里就涉及到一个连接状态了,首先得理解下http的工作原理,http协议是建立在tcp协议基础之上,当浏览器需要从服务器获取数据的时候,会发出一次http请求。


http会通过tcp建立起一个到服务器的连接通道,当本次请求需要的数据完毕后,http会立即将tcp连接断开,这个过程是很短的。


所以http连接是一种短连接,是一种无状态的连接。但是tcp的连接只要我们不通过代码把连接关闭,这个连接就会在客户端和服务端的进程中一直存在,相关状态数据会一直保存着,直到无响应状态持续了默认关闭时间后自动断开。



当短期请求量过大时,这就可能导致了"套接字资源耗尽异常",因此,为了解决这个问题,想到不释放HttpClient,将它作为单例一直使用,实现单例方式有很多种。


如使用单例模式,只生成一个HttpClient


private static HttpClient _httpClient = null;public HttpClient CreateHttpClient(){    if (_httpClient == null) _httpClient = new HttpClient();    return _httpClient;}


亦或是在初始化时完成单例注入,创建一个IHttpClient接口,及相应的实现StandardHttpClient,实现类种加入HttpClient属性,在实现类构造函数中完成初始化后便可直接使用该实现类完成资源请求工作。


//在startup中完成单例注入services.AddSingleton<IHttpClient, StandardHttpClient>();public interface IHttpClient{    //do something}public class StandardHttpClient : IHttpClient{    private HttpClient _client;    public StandardHttpClient()    {        _client = new HttpClient();    }    //do something...}


虽然这样解决了"套接字资源耗尽异常",但是又带来了新的问题,熬不过DNS生存时间(TTL),当主机 DNS 更新时,又可能产生异常,提示无法解析主机名称,因为单例HttpClient不会随着主机DNS更新而更新,Singleton HttpClient doesn't respect DNS changes。


An error occurred while sending the request. Couldn't resolve host name An error occurred while sending the request. Couldn't resolve host name


二、现有HttpClient使用方式


在.NET Core 2.1后,微软引入了HttpClientFactory彻底解决这个问题,工厂模式的职责是负责创建对象,这个类主要负责创建HttpClient实例


首先在StartUp中注册,可能会提示安装这个Nuget包


services.AddHttpClient();


该方法内部实现过程可以浏览:https://www.cnblogs.com/lizhizhang/p/9502862.html


其次,在需要使用时,使用构造函数注入即可


[Route("api/[controller]")][ApiController]public class HttpClientController : ControllerBase{    IHttpClientFactory _httpClientFactory;    public HttpClientController(IHttpClientFactory httpClientFactory)    {        _httpClientFactory = httpClientFactory;    }    [HttpGet]    [Route(nameof(Index))]    public async Task<IActionResult> Index()    {        var client = _httpClientFactory.CreateClient();        var result = await client.GetAsync("http://aspnetcore.online/api/resource/getresource");        return Ok(result);    }}


具体实现原理简述为:HttpClientFactory内部管理着一个连接句柄池,对每一个HttpClient使用一个句柄进行跟踪管理,当该实例使用完毕后,句柄仍然控制资源释放,在短期大量处理时,可以将这部分句柄完成对不同实例的跟踪管理,使得句柄,也就是相应的套接字生命周期延长,对套接字完成了复用。


推荐阅读

(点击标题可跳转阅读)

.NET Core中正确使用HttpClient的姿势

HttpClient在.NET Core中的正确打开方式

.NET Core 2.2对HttpClient到底做了什么?


看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

喜欢就点一下「好看」呗~

登录查看更多
0

相关内容

【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【实用书】流数据处理,Streaming Data,219页pdf
专知会员服务
76+阅读 · 2020年4月24日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
FlowQA: Grasping Flow in History for Conversational Machine Comprehension
专知会员服务
29+阅读 · 2019年10月18日
基于RASA的task-orient对话系统解析(一)
AINLP
16+阅读 · 2019年8月27日
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
使用 C# 和 Blazor 进行全栈开发
DotNet
6+阅读 · 2019年4月15日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
IPSec | IKE密钥交换原理
计算机与网络安全
18+阅读 · 2018年12月23日
.NET Core 环境下构建强大且易用的规则引擎
设计和实现一款轻量级的爬虫框架
架构文摘
13+阅读 · 2018年1月17日
Deep learning for cardiac image segmentation: A review
Arxiv
21+阅读 · 2019年11月9日
Arxiv
35+阅读 · 2019年11月7日
Logically-Constrained Reinforcement Learning
Arxiv
3+阅读 · 2018年12月6日
Deep Reinforcement Learning: An Overview
Arxiv
17+阅读 · 2018年11月26日
Semantics of Data Mining Services in Cloud Computing
Arxiv
4+阅读 · 2018年10月5日
VIP会员
相关VIP内容
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【实用书】流数据处理,Streaming Data,219页pdf
专知会员服务
76+阅读 · 2020年4月24日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
FlowQA: Grasping Flow in History for Conversational Machine Comprehension
专知会员服务
29+阅读 · 2019年10月18日
相关资讯
基于RASA的task-orient对话系统解析(一)
AINLP
16+阅读 · 2019年8月27日
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
使用 C# 和 Blazor 进行全栈开发
DotNet
6+阅读 · 2019年4月15日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
IPSec | IKE密钥交换原理
计算机与网络安全
18+阅读 · 2018年12月23日
.NET Core 环境下构建强大且易用的规则引擎
设计和实现一款轻量级的爬虫框架
架构文摘
13+阅读 · 2018年1月17日
Top
微信扫码咨询专知VIP会员