程序员节应该写博客之.NET下使用HTTP请求的正确姿势

  • 时间:2017-12-08
  • 分类:数据库/系统
  • 1019 人浏览
[导读]程序员节应该写博客之.NET下使用HTTP请求的正确姿势一、前言去年9月份的时候我看到过外国朋友关于.NET Framework下HttpClient缺陷的分析后对HttpClient有了一定的了解。

程序员节应该写博客之.NET下使用HTTP请求的正确姿势

一、前言

去年9月份的时候我看到过外国朋友关于.NET Framework下HttpClient缺陷的分析后对HttpClient有了一定的了解。前几日也有园友写了一篇关于HttpClient的分析文章, 于是我想深入探索一下在.NET下使用HTTP请求的正确姿势。姿势不是越多越好, 而在于精不精。如果不深入了解, 小朋友可能会这样想: 啊, 这个姿势不High, 那我换一个吧, 殊不知那一个姿势也有问题啊, 亲。

中文版: https://oschina.net/news/77036/httpclient

英文版: https://www.infoq.com/news/2016/09/HttpClient

张大大版: http://www.cnblogs.com/lori/p/7692152.html

 

二、准备好床和各种姿势

1. 研究姿势必然是要先准备好支撑点, 作为一个传统的人, 还是比较喜欢床。

.NET Framework, .NET CORE Windows, .NET CORE Linux, .NET CORE Mac

2. 姿势有以下几种, 如果小朋友们有各特别的可以告诉我呀, 我很乐于尝试的。

HttpClient, WebClient, HttpWebRequest

 

三、让我们大干一场吧

Windows下统计端口使用的命令: netstat -ano | find "{port}" /c 

Linux 下统计端口使用的命令:  netstat -nat|grep -i "{port}"|wc -l

HttpWebRequest 测试代码如下

  .NET Framework   .NET Core Windows  .NET Core Linux .NET Core Mac HttpWebRequest 2 端口占用数迅速攀升到1000+ 性能很差, 端口占用数攀升到70+并稳定    

WebClient因为有IDisposable接口, 于是我做两份测试

 
.NET Framework   .NET Core Windows  .NET Core Linux .NET Core Mac WebClient  2 端口占用数迅速攀升到1000+ 性能较差, 端口占用数攀升到400+稳定   

   .NET Framework   .NET Core Windows  .NET Core Linux  .NET Core Mac  WebClient  2  端口占用数迅速攀升到1000+  端口占用数迅速攀升到1000+   

HttpClient有IDisposable接口, 也做两份测试

  .NET Framework .NET Core Windows .NET Core Linux .NET Core Mac HttpClient 10 10 10  

  .NET Framework .NET Core Windows .NET Core Linux .NET Core Mac HttpClient 端口占用数迅速攀升到1000+ 端口占用数迅速攀升到1000+ 性能较差, 端口占用数攀升到200+   

结论

  .NET Framework .NET Core Windows .NET Core Linux .NET Core Mac HttpWebRequest OK Abnormal Abnormal   WebClient OK Abnormal Abnormal   HttpClient(每个线程一个对象) OK  OK OK   HttpClient(using) Abnormal Abnormal Abnormal     

有意思的细节与疑问

1. WebClient和HttpWebRequest为什么在10个线程下端口数为2并且都为2

2. Linux下并行性能明显变差

 

四、追根溯源

下载.net45源码和corefx源码

http://referencesource.microsoft.com/ 右上角Download

https://github.com/dotnet/corefx

 

1. 分析.NET Core下WebClient的代码, 发现它是使用WebRequest即HttpWebRequest来请求数据

 

2. 分析.NET Core下HttpWebRequest的代码找到SendRequest方法

熟悉吗"http://images2017.cnblogs.com/blog/40347/201710/40347-20171024185330426-2043412833.png" alt="" />

 

4. 我们再回过头来看.NET Framework下为什么HttpWebRequest和WebClient是正常的, WebClient依然是使用的HttpWebRequest, 因此推断.NET Framework的HttpWebRequest的实现与.NET Core是不一致的。简单的查找代码, 果然每一个Http请求是由ServicePointManager管理的ServicePoint来实现的, 并且ServicePoint是使用.NET下Socket来实现的, 一切就明了了。现在对刚才说的 “WebClient和HttpWebRequest为什么在10个线程下端口数为2并且都为2”有感觉了吧?我们把刚才的测试代码再加上一行

  .NET Framework .NET Core Windows .NET core Linux .NET Core Mac HttpWebRequest 10   迅速攀升到1000+ 性能很差, 攀升到70+并稳定  

 

 

大家看.NET Core下虽然可以设置 ServicePointManager.DefaultConnectionLimit = 10; 但是依然没什么卵用...  原因也很明显, HttpWebRequest根本没有使用ServicePointManager做管理。在我查了源码后虽然.NET Core实现了ServicePointManager和ServicePoint, 不过已经迁到另外一个项目下面, 也未发现有什么作用。所以大家千万要注意,不要以为在.NET Core可以设置ServicePointManager.DefaultConnectionLimit这个值了, 就以为.NET Framework下的效果会一致( 其它地方同理)

 

5. HttpClient在.NET Framework下的代码我没有找到, ILSpy也查看不了, 但猜想应该是和.NET Core下一致的, 所以才会有一样的表象, 有大神知道的可以告诉我一下。

 

五、好累啊, 终于交差了, 就是不知道满足不满足

1. 在.NET Framework下尽量使用HttpWebRequest或者WebClient, 并且根据你自己的多线程情况设置 ServicePointManager.DefaultConnectionLimit的值, 以及ThreadPool.SetMinThreads(200, 200)的值

2. 在.NET Framework下如果一定要使用HttpClient, 则应该一个线程使用一个HttpClient对象, 这样不会出现端口被耗尽的情况

3. 在.NET Core 2.0下只有HttpClient一条路选, 并且一个线程使用一个HttpClient对象, 当然也许我们可以参照.NET Framework下的代码重新实现一个ServicePointManager管理的HttpWebRequest, 这是后话了

 

来源:本文为线上采编,如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除!
标签: HTTP请求 .NET