前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Asp.Net Core中HttpClient的使用方式

Asp.Net Core中HttpClient的使用方式

作者头像
心莱科技雪雁
发布2019-03-11 15:05:06
1.2K0
发布2019-03-11 15:05:06
举报
文章被收录于专栏:雪雁的专栏雪雁的专栏

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

一原先HttpClient使用方式

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

代码语言:javascript
复制
//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方式提交并返回相应的内容,都是可以直接使用。

代码语言:javascript
复制
//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

代码语言:javascript
复制
private static HttpClient _httpClient = null;
public HttpClient CreateHttpClient()
{
    if (_httpClient == null) _httpClient = new HttpClient();
    return _httpClient;
}

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

代码语言:javascript
复制
//在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。

代码语言:javascript
复制
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 Core2.1后,微软引入了HttpClientFactory彻底解决这个问题,工厂模式的职责是负责创建对象,这个类主要负责创建HttpClient实例

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

代码语言:javascript
复制
 services.AddHttpClient();

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

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

代码语言:javascript
复制
[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使用一个句柄进行跟踪管理,当该实例使用完毕后,句柄仍然控制资源释放,在短期大量处理时,可以将这部分句柄完成对不同实例的跟踪管理,使得句柄,也就是相应的套接字生命周期延长,对套接字完成了复用。

本文转载于博客园 原文作者:微笑刺客D 博客园原文链接 https://ckexp.cnblogs.com/p/10426170.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 麦扣聊技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一原先HttpClient使用方式
  • 二、现有HttpClient使用方式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档