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

 更新时间:2019-04-17 21:43:26   作者:佚名   我要评论(0)

前言


在 Asp.Net Core 1.0 时代,由于设计上的问题, HttpClient 给五分时时彩开发者带来了无尽的困扰,用 Asp.Net Core

五分时时彩开发团队的话来说就是:我们注意到,Http

前言

在 Asp.Net Core 1.0 时代,由于设计上的问题, HttpClient 给五分时时彩开发者带来了无尽的困扰,用 Asp.Net Core
五分时时彩开发团队的话来说就是:我们注意到,HttpClient 被很多五分时时彩开发人员不正确的使用。得益于 .Net Core
不断的版本快速升级;

问题来源

长期以来,.NET五分时时彩开发者都通过下面的方式发送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

可是,当我们试图运行下面的测试:

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"

你会发现本地开启了10个端口,这说明HttpClient的工作原理其实跟我们认为的IDisposable是有区别的,如果你把HttpClient用作大规模的Http请求,实际上会创建很多个Http连接,而且这些资源并不能被立即释放。一个显而易见的改进方法是共享同一个HttpClient实例,从而达到节约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资源,但是这个方案会引发新的问题:由于这个Http连接始终保持连接状态,所以当请求地址的DNS发生更新的时候并不会应用到这个Http连接上。这个问题在微服务,高可用时代更加常见Singeton HttpClient doesn't respect DNS changes。

最终,一个叫做HttpClientFactory的开源实现用来彻底解决这个问题。微软也将HttpClientFactory集成在了.NET Core中。

在.NET Core中创建HttpClient
1.添加Nuget

Microsoft.Extensions.Http 

2.在Dependency Injection容器中注册服务

services.AddHttpClient();

3. 使用构造器注入使用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创建出来的HttpClient可能是同一个配置和参数,如果你需要不同配置的HttpClient,你可以通过“起名字的”的方式注册不同的HttpClient。

services.AddHttpClient("baidu", c =>
{
 c.BaseAddress = new Uri("https://www.baidu.com");
 c.DefaultRequestHeaders.Add("Accept", "application/json");
});

一旦注册了一个名叫“baidu"的HttpClient,你就可以通过下面的方式来建创建HttpClient:

var client = _clientFactory.CreateClient("baidu");

5.集成Polly

Polly是一个用来故障处理库,它允许五分时时彩开发者在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));

当然还有一些高阶用法,详见Initiate HTTP requests,总之HttpClientFactory提供了一种高效实用HttpClient的方式,如果你还在自己new HttpClient,请赶快试试新的方案吧。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

您可能感兴趣的文章:

  • C# HttpClient Cookie验证解决方法
  • 谈谈HttpClient使用详解
  • ASP.NET MVC Web API HttpClient简介
  • 通过HttpClient 调用ASP.NET Web API示例
  • .NET Core中使用HttpClient的正确姿势
  • .NET Core 2.1中HttpClientFactory的最佳实践记录
  • ASP.NET Core针对一个使用HttpClient对象的类编写单元测试详解
  • Asp.Net Core2.1前后使用HttpClient的两种方式

相关文章

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

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

    前言 在 Asp.Net Core 1.0 时代,由于设计上的问题, HttpClient 给五分时时彩开发者带来了无尽的困扰,用 Asp.Net Core 五分时时彩开发团队的话来说就是:我们注意到,Http
    2019-04-17
  • 如何使用Rotativa在ASP.NET Core MVC中创建PDF详解

    如何使用Rotativa在ASP.NET Core MVC中创建PDF详解

    前言 在本文中,我们将学习如何使用Rotativa.AspNetCore工具从ASP.NET Core中的视图创建PDF。如果您使用ASP.NET MVC,那么Rot&#8203;&#8203;ativa工具已经可用
    2019-04-17
  • 详解jQuery-each()方法

    详解jQuery-each()方法

    jquery中有隐式迭代,不需要我们再次对某些元素进行操作。但是如果涉及到不同元素有不同操作,需要进行each遍历。本文利用10个li设置不同的透明度的案例,对e
    2019-04-17
  • ASP.NET Core针对一个使用HttpClient对象的类编写单元测试详解

    ASP.NET Core针对一个使用HttpClient对象的类编写单元测试详解

    介绍 几年前,微软引入了HttpClient类来替代HttpWebRequest来发送Web请求。这个新的类更易于使用,更加简洁,更具有异步性,且易于扩展。 HttpClient类有一
    2019-04-17
  • 详解React项目中碰到的IE问题

    详解React项目中碰到的IE问题

    最近接手一个React项目,在IE下碰到了俩问题 IE11报错如下: 跟踪一下之后,发现是一些其他的npm包里面用到了startsWith这个方法,可以自己polyfill一下:
    2019-04-17
  • 你可能不知道的CORS跨域资源共享

    你可能不知道的CORS跨域资源共享

    什么是CORS? 默认情况下,为预防某些而已行为,浏览器的XHR对象只能访问来源于同一个域中的资源。但是我们在日常实际五分时时彩开发中,常常会遇到跨域请求的需求,
    2019-04-17
  • Asp.net Core Jenkins Docker实现一键化部署的实现

    Asp.net Core Jenkins Docker实现一键化部署的实现

    写在前面 在前段时间尝试过用Jenkins来进行asp.net core 程序在IIS上面的自动部署。大概的流程是Jenkins从git上获取代码 最开始Jenkins是放在Ubuntu的Doc
    2019-04-17
  • asp.net core2.2多用户验证与授权示例详解

    asp.net core2.2多用户验证与授权示例详解

    前言 asp.net core2.2 用户验证 和授权有很详细和特贴心的介绍,我感兴趣的主要是这两篇: cookie身份验证 基于角色的授权 我的项目有两类用户: 微
    2019-04-17
  • 详解js动态获取浏览器或页面等容器的宽高

    详解js动态获取浏览器或页面等容器的宽高

    首先说一下js动态获取浏览器或页面等容器的宽高的方法大体有哪些: 网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.client
    2019-04-17
  • Asp.net mvc在view中用C#代码动态创建元素

    Asp.net mvc在view中用C#代码动态创建元素

    1、 在view中可以用c#代码foreach动态创建元素 2、 不加@{}下图中c#代码变成了白色,无法识别了。 总结 以上就是这篇文章的全部内容了,希望本文的内容对
    2019-04-17

最新评论