引言:

  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. Navicat 连接MySQL数据库 报错2059 - authentication plugin 'caching_sha2_password'的解决办法

    #在数据库的命令行中输入以下代码即可解决,密码必须要修改 可以再次执行将密码改回来. use mysql; ALTER USER 'root'@'localhost' IDENTIFIED WITH ...

  2. Oracle EBS when-validate-record 个性化无效果

    在对FORM进行个性化时,针对对应块添加 when-validate-record ,结果做实验的时候无效果. 原因: FORM 中对应的 BLOCK 没有 when-validate-record ...

  3. web前端(13)—— 了解JavaScript,JavaScript的引入方式

    从本篇博文开始,将进入web前端方便最关键最重要的部分——javascript,学到后面你就知道它真的太重要了 什么是JavaScript JavaScript一种直译式的脚本语言,是一种动态类型.弱 ...

  4. vue2 学习笔记2

    文中例子代码请参考github 品牌管理案例 添加新品牌 <body> <div id="app"> <div class="panel p ...

  5. June 5. 2018 Week 23rd Tuesday

    Learn to let go and be clear of where you really want to head for. 学会放手,同时也要弄清楚自己的真正所爱. From Kissing ...

  6. nodejs前后分离

    proxy: { '/api': { target: 'http://localhost:3000/', pathRewrite: {'^/api' : ''}, changeOrigin: true ...

  7. mysql 数据库基础命令

    数据库命令: 进入 mysql 库; use mysql; 查看用户权限 select * from user where user='root' \G; 创建数据库 create database ...

  8. Linux系统在信息社会的发展

    Linux系统在信息社会的发展 随着信息技术的高速发展并迅速渗透到社会生活的各个方面,Linux日益成为人们学习.工作.生活不可缺少的基本工具,再过不了几年,不会使用Linux,就会象不识字一样使人举 ...

  9. elasticSearch学习安装

    资料: 1.Elasticsearch学习,请先看这一篇! https://blog.csdn.net/laoyang360/article/details/52244917 2. linux下ela ...

  10. centos7下kubernetes(2。kubernetes---start,重要概念)

    Cluster cluster是计算,存储和网络资源的集合,kubernetes是利用这些资源运行各种基于容器的应用 Master Master是cluster的大脑,他的主要职责是调度,即决定应用在 ...