引言:

  ASP.NET Core2.1 中出现了一个新的 HttpClientFactory 功能, 它有助于解决开发人员在使用 HttpClient 实例从其应用程序中访问外部 web 资源时可能遇到的一些常见问题。关于HttpClientFactory 到底解决了那些HttpClient的严重问题,下面是我罗列出来的(原文来自于:https://www.infoq.com/news/2016/09/HttpClient)

  (1)在处理HttpClient对象的时候不会立即关闭socket。

  (2)太多的实例影响性能

  (3)单例的HttpClient或者共享HttpClient实例,不遵守DNS 生存时间 (TTL) 设置。(这个问题我也不太明白,具体怎么重现这个问题,我下去再研究研究。)

HttpClientFactory这个小可爱,解决了上面的所有问题,他也是ASP.NET Core2.1最新特点之一,下面详细聊聊HttpClient存在的这些问题。

一、HttpClient存在的问题

  由于设计错误、bug 和文档不正确等因素, 导致在.Net中正确使用HttpClient 出奇的难。因此, 在生产环境中看起来正常工作的应用程序可能会在负载大的情况下产生性能和运行时故障的问题。

  为了理解我们为什么遇到这种情况, 我们首先要看另一个面向连接的类: SqlConnection。 这个类实现了IDisposable接口,所以绝大多数开发人员都是这样写的,实例如下:

  using (var con = new SqlConnection(connectionString)) {
    
con.open();
    
//use the connection here
  } //this closes the connection  

虽然,这个例子在解释HttpClient存在的问题不是很到位,但是使用这种方式,来写上面的代码,是没错的。如果你尝试这把这种模式应用到实现了IDisposable接口的HttpClient,则会遇到一些很奇怪的问题。具体的说,它会打开比实际需要更多的socket,加重了服务器的负载。此外使用using语句是不会关闭这些套接字的,相反,在应用程序停止使用它们时,会关闭几分钟。

Connection Pooling

回到 SqlConnection 示例中, 大多数面向连接的资源都是有连接池的。当您 "打开 " 数据库连接时, 它首先检查池中是否有可用的、未使用的连接。如果它找到一个, 将重用它, 而不是创建一个新的连接。

同样, 当您 "关闭 " SqlConnection 它只是将连接释放到链接池中。最终, 一个单独的进程可能会关闭长时间未使用的连接。

HttpClient 不这样做。当您处理它时, 它将启动关闭它所控制的套接字的过程。这意味着下次有请求时, 您必须经过一个全新的连接周期。如果您的网络有很高的延迟或您的连接是安全的, 则这会特别痛苦, 因为后者需要新一轮的 SSL/TLS 协商。

Closing a Socket Takes Four Minutes

如上所述,关闭套接字不是一个快速的过程。 当你“关闭”套接字时,你真正在做的是将它置于TIME_WAIT状态。 Windows将在此状态下保持连接240秒,以防万一剩余的数据包仍在传输中。

这使您更有可能耗尽可用套接字的数量,从而导致运行时错误,例如“无法连接到远程服务器.System.Net.Sockets.SocketException:每个套接字地址只有一种用法(协议/ 网络地址/端口通常是允许的“。

下面我们来实践一下,看看真相:

示例演示:(注意使用的是.Net Core 1.0)

using System;
using System.Net.Http;
using System.Threading.Tasks; namespace ConsoleApp2
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Starting connections");
for (int i = ; i < ; i++)
{
using (var client = new HttpClient())
{
var result = await client.GetAsync("http://aspnetmonsters.com/");
            Console.WriteLine(result.StatusCode);
          }
       }
      Console.WriteLine("Connections done");
      Console.ReadKey();
    }
  }
}

这将会打开10个请求,并以get的方式,去请求博客园,我们只打印出状态码。

输出结果:

到这个地步,可能我们就会很高兴,搞定!闪人!,真的搞定了吗?我的小可爱,下面我们使用netstat 工具并查看运行它的机器上的套接字状态,我们将看到:

看到没,我的应用程序已经执行完了,但是,仍然有很多链接在打开上面图示中的主机,它们都处于TIME_WAIT状态,这意味这我们在应用程序这边已经把链接关闭了,但是我们仍然在等待查看,是否有额外的数据包进来,使用这些链接。因为它们可能在网络的某个地方已经被延迟,下面我们来看一张TCT/IP图,该图引自(https://www4.cs.fau.de/Projects/JX/Projects/TCP/tcpstate.html)

Windows将在此状态下保持连接240秒(由[HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ TcpTimedWaitDelay]设置)。 Windows可以快速打开新套接字的速度有限,因此如果您耗尽连接池,那么您可能会看到如下错误:

Unable to connect to the remote server
System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.

在谷歌搜索会给你一些关于减少连接超时的可怕建议。 事实上,当在服务器上运行着正确使用HttpClient或类似构造的应用程序时,减少超时可能会导致其他不利后果。 我们需要了解“正确”意味着什么,并去修复底层的问题而不是去修补机器级的变量。

如果我们共享一个HttpClient实例,那么我们可以通过重用它们来减少套接字的浪费:

请注意,我们只为整个应用程序共享了一个HttpClient实例。 仍然可以正常工作(实际上由于套接字重用而快一点)。 Netstat现在只显示:

好了,总结一下:在.Net Core 1.0之前的版本,使用的时候需要注意下面的两点:

(1)确保你的HttpClient 是 static

(2)不要丢弃或包装HttpClient 在一个using块中。

小弟我才疏学浅,有不对的地方可以指出来,共同探讨。其实,我们一直使用using把它包起来,也是没错的,是因为HttpClient实现了IDisposable ,但是HttpClient就比较特殊,这不怪我们,文档就是错误的。

二、HttpClientFactory in ASP.NET Core 2.1就解决了上面所有的问题

HttpClientFactory 这个小可爱,就解决了上面的所有问题,她也是ASP.NET Core 2.1中最新特点之一,有了她我们就不用关心如何创建HttpClient,又如何释放它。关于如何使用它,博客园中的有介绍的,我这里就不再讲述了。

具体请参考:https://www.cnblogs.com/willick/p/9640589.html

三、总结

到这里该系列文章的第一篇就讲完了,有不对的地方,还请大佬们能指出来,共同探讨,好了,希望对你有所帮助,该系列文章,每周末更新,爱看不看,哈哈哈~~~~~~

参考文章:

(翻译)https://www.infoq.com/news/2016/09/HttpClient

(翻译)https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

作者:郭峥

出处:http://www.cnblogs.com/runningsmallguo/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

ASP.Net Core2.1中的HttpClientFactory系列一:HttpClient的缺陷的更多相关文章

  1. ASP.Net Core2.1中的HttpClientFactory系列二:集成Polly处理瞬态故障

    前言:最近,同事在工作中遇到了使用HttpClient,有些请求超时的问题,辅导员让我下去调研一下,HttpClinet的使用方式已经改成了之前博客中提到的方式,问题的原因我已经找到了,就是因为使用了 ...

  2. 在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制

    Swashbuckle.AspNetCore3.0 介绍 一个使用 ASP.NET Core 构建的 API 的 Swagger 工具.直接从您的路由,控制器和模型生成漂亮的 API 文档,包括用于探 ...

  3. 【翻译】asp.net core2.0中的token认证

    原文地址:https://developer.okta.com/blog/2018/03/23/token-authentication-aspnetcore-complete-guide token ...

  4. ASP.NET Core2.1 中如何使用 Cookie和Session

    https://blog.csdn.net/canduecho/article/details/80651853 ASP.NET Core2.1的官方项目模板在创建的Razor Pages和MVC项目 ...

  5. asp.net core2.0中异常的处理

    最近在开发中遇到一些关于如何抛出异常的困惑,在qq群里进行了讨论,有些人认为抛出异常是有理由的,可以对业务流程进行控制,而有些认为抛出异常会导致程序性能低下,我写一些自己的心得吧. 异常的全局处理 a ...

  6. 在ASP.NET Core2.0中使用百度在线编辑器UEditor(转)

    一.起因 UEditor是百度旗下的富文本编辑器,对于后端上传处理仅提供了Asp.Net 版的支持. 如果想在.Net Core项目中使用,那么后台上传接口需要重构. UEditorNetCore:百 ...

  7. Asp.Net Core2.2 源码阅读系列——控制台日志源码解析

      为了让我们第一时间知道程序的运行状态,Asp.Net Core 添加了默认的日志输出服务.这看起来并没有什么问题,对于开发人员也相当友好,但如果不了解日志输出的细节,也有可能因为错误的日志级别配置 ...

  8. asp.net core2.0中网站发布的时候,怎么样才配置才可以使视图文件不被打包进去?

    默认设置可真是坑~~ https://q.cnblogs.com/q/99680/

  9. asp.net core2.0中网站发布的时候,视图文件不被打包成dll

    项目csproj文件里面加 <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <Target ...

随机推荐

  1. 深圳市共创力推出《以用户为中心的设计UCD方法与实战》课程!

    以用户为中心的设计(UCD)方法与实战 课程特色 现在以市场为中心.科技为基础.体验为卖点的商业社会里,用户体验是赢得用户青睐的关键特性.苹果.google.腾讯等顶级企业的成功充分说明了这一点.如何 ...

  2. JS辨别访问浏览器判断是android还是ios系统

    function isIOSOrAndroid() { var browser = { versions: function() { var u = navigator.userAgent, app ...

  3. python3接收、解析邮件

    邮件接收 python3可以使用poplib.POP3进行邮件接收,具体如下: import poplib from email.parser import Parser def get_email( ...

  4. openstack Ocata版本 python

    from keystoneauth1.identity import v3 from keystoneauth1 import session from novaclient import clien ...

  5. shell编程-输入/输出重定向(十一)

    linux中文件描述符 linux跟踪打开文件,而分配的一个数字,通过这个数字可以实现对文件的读写操作 用户可以自定义文件描述符范围是:3-max,max跟用户的ulimit –n 定义数字有关系,不 ...

  6. AspNet mvc的一个bug

    [HttpPost] public ActionResult updateLoan(TuWenMilitaryRank entity) 使用mvc绑定表单 每次绑定的对象都为null,查看Reques ...

  7. sql生成连续日期(年份、月份、日期)

    此随笔主在分享日常可能用到的sql函数,用于生成连续日期(年份.月份.日期) 具体的看代码及效果吧! -- ============================================= ...

  8. 同步下的资源互斥:停运保护(Run-Down Protection)机制

    背景 近期在学习ProcessHacker的源码,Process Hacker是一个免费的.功能强大的"任务管理器",可用于监听系统资源的使用情况,调试软件以及检测恶意程序.使用中 ...

  9. C++多线程同步技巧(三)--- 互斥体

    简介 Windows互斥对象机制. 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问,在线程同步与保证程序单体运行上都有相当大的用处. 代码 ...

  10. PHP编程效率

    1.如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍.2.$row['id'] 的速度是$row[id]的7倍.3.echo 比 print 快,并且使用echo的 ...