.net4.5中HttpClient使用注意点
.net4.5中的HttpClinet是个非常强大的类,但是在最近实际项目运用中发现了些很有意思的事情。
起初我是这样用的:
using (var client = new HttpClient())
{
}
但是发现相较于传统的HttpRequest要慢上不少,后来查阅资料,发现HttpClient不应该每使用一次就释放,因为socket是不能及时释放的,需要把HttpClient作为静态的来使用。
private static readonly HttpClient Client = new HttpClient();
再来后在使用过程当中需要密集的发送GET请求,但是总感觉慢,用fiddler查看,发现每次请求只并发了2次,代码是用semaphoreSlim信号量来控制的,最大数量为10。而电脑的配置为r5 1600,系统为win7 x64,按照道理来说并发10是没问题的,考虑到是否因为 ServicePointManager.DefaultConnectionLimit 限制了并发的数量,我修改了 ServicePointManager.DefaultConnectionLimit 的值为100,再次运行程序发现并发的数量还是2,于是上stackoverflow找到了这篇文章:
https://stackoverflow.com/questions/16194054/is-async-httpclient-from-net-4-5-a-bad-choice-for-intensive-load-applications
根据上面文章所讲,似乎HttpClient是不遵守ServicePointManager.DefaultConnectionLimit的,并且在密集应用中HttpClient无论是准确性还是效率上面都是低于传统意义上的多线程HttpRequest的。但是事实确实是这样的吗?如果真的是要比传统的HttpRequest效率更为底下,那么巨硬为什么要创造HttpClient这个类呢?而且我们可以看到在上面链接中,提问者的代码中HttpClient是消费了body的,而在HttpRequest中是没有消费body的。带着这样的疑问我开始了测试。
var tasks = Enumerable.Range(1, 511).Select(async i =>
{
await semaphoreSlim.WaitAsync();
try
{
var html = await Client.GetStringAsync($"http://www.fynas.com/ua/search?d=&b=&k=&page={i}");
var doc = parser.Parse(html);
var tr = doc.QuerySelectorAll(".table-bordered tr:not(:first-child) td:nth-child(4)").ToList();
foreach (var element in tr)
{
list.Enqueue(element.TextContent.Trim());
}
doc.Dispose();
}
finally
{
semaphoreSlim.Release();
}
});
上面这段代码,是采集一个UserAgent大全的网站,而我的HttpClient及ServicePointManager.DefaultConnectionLimit是这样定义的:
static Program()
{
ServicePointManager.DefaultConnectionLimit = 1000;
}
private static readonly HttpClient Client = new HttpClient(new HttpClientHandler(){CookieContainer = new CookieContainer()});
经过多次试验,我发现,HttpClient是遵守了ServicePointManager.DefaultConnectionLimit的并发量的,默认还是2,大家仔细观察一下不难发现其实HttpClient是优先于ServicePointManager.DefaultConnectionLimit设置的,也就是说HttpClient比ServicePointManager.DefaultConnectionLimit要先实例化,接下来我把代码修改为这样:
static Program()
{
ServicePointManager.DefaultConnectionLimit = 1000;
Client = new HttpClient(new HttpClientHandler() { CookieContainer = new CookieContainer() });
}
private static readonly HttpClient Client;
然后再次运行,打开fiddler进行监视,发现这个时候程序就能够正常的进行并发10来访问了。
而HttpClient中的HttpMessagehandle也是一个非常有趣的地方,我们可以进行实际的情况来进行包装一下HttpMessageHandle,比如下面这段代码实现了访问失败进行重试的功能:
public class MyHttpHandle : DelegatingHandler
{
public MyHttpHandle(HttpMessageHandler innerHandler):base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
for (int i = 0; i < 2; i++)
{
var response = await base.SendAsync(request, cancellationToken);
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
await Task.Delay(1000, cancellationToken);
}
}
return await base.SendAsync(request, cancellationToken);
}
}
在实例化HttpClient的时候,把我们定义的handle传递进去:
private static readonly HttpClient Client = new HttpClient(new MyHttpHandle(Handler))
这样就实现了总共进行三次访问,其中任意一次访问成功就返回成功的结果,如果第二次访问还没成功就直接返回第三次访问的结果。
.net4.5中HttpClient使用注意点的更多相关文章
- <pages validateRequest="false"/>在.net4.0中无效的问题
再web.config中设置<pages validateRequest="false"/>在.net4.0中无效的问题 解决方案: <system.web> ...
- Java中httpClient中三种超时设置
本文章给大家介绍一下关于Java中httpClient中的三种超时设置小结 在Apache的HttpClient包中,有三个设置超时的地方: /* 从连接池中取连接的超时时间*/ ConnManage ...
- c# 中HttpClient访问Https网站
c# 中HttpClient访问Https网站,加入如下代码: handler = new HttpClientHandler() ;handler.AllowAutoRedirect = true; ...
- C# 中HttpClient的使用中同步异步问题
项目中遇到了这样的问题: 第一次 :HttpResponseMessage response = await httpClient.PostAsync(url, null);发送了一个post异步请求 ...
- 关于.net4.0中的Action委托
在使用委托时,若封装的方法无返回值,并且参数在0-7个,可考虑使用.Net4.0中的Action委托,建议使用系统自带的,减少自定义 public delegate void Action<in ...
- C#中使用Redis学习二 在.NET4.5中使用redis hash操作
上一篇>> 摘要 上一篇讲述了安装redis客户端和服务器端,也大体地介绍了一下redis.本篇着重讲解.NET4.0 和 .NET4.5中如何使用redis和C# redis操作哈希表. ...
- 【转】C#中使用Redis学习二 在.NET4.5中使用redis hash操作
摘要 上一篇讲述了安装redis客户端和服务器端,也大体地介绍了一下redis.本篇着重讲解.NET4.0 和 .NET4.5中如何使用redis和C# redis操作哈希表.并且会将封装的一些代码贴 ...
- C#中HttpClient使用注意:预热与长连接
最近在测试一个第三方API,准备集成在我们的网站应用中.API的调用使用的是.NET中的HttpClient,由于这个API会在关键业务中用到,对调用API的整体响应速度有严格要求,所以对HttpCl ...
- 如何在.net4.0中使用.net4.5的async/await
推荐文章: http://www.cnblogs.com/hj4444/p/3857771.html http://www.cnblogs.com/dozer/archive/2012/03/06/a ...
随机推荐
- 【Notification】屏蔽特定应用的通知提示
须要默认屏蔽特定app的通知提示 设置app是否接收通知的界面 点击每一个条目进去的界面 AppNotificationSettings extends SettingsPreferenceFragm ...
- 解决 PclZip 中文乱码问题
在使用 Pclzip 时出现无法压缩/解压文件的现象,追踪错误信息发现无法打开文件/文件夹.可是文件夹权限正确,打印文件路径之后发现是乱码. 出现这个问题的解决办法是windows下zip内的 ...
- Struts2中validate数据校验的两种常用方法
本文主要介绍Struts2中validate数据校验的两种方法及Struts2常用校验器. 1.Action中的validate()方法 Struts2提供了一个Validateable接口,这个接 ...
- 快看Sample代码,速学Swift语言(1)-语法速览
Swift是苹果推出的一个比较新的语言,它除了借鉴语言如C#.Java等内容外,好像还采用了很多JavaScript脚本里面的一些脚本语法,用起来感觉非常棒,作为一个使用C#多年的技术控,对这种比较超 ...
- 聊聊js中的typeof
内容: 1.typeof 2.值类型和引用类型 3.强制类型转换 typeof 官方文档:typeof 1.作用: 操作符返回一个字符串,指示未经计算的操作数的类型. 2.语法: typeof ope ...
- 用keras做SQL注入攻击的判断
本文是通过深度学习框架keras来做SQL注入特征识别, 不过虽然用了keras,但是大部分还是普通的神经网络,只是外加了一些规则化.dropout层(随着深度学习出现的层). 基本思路就是喂入一堆数 ...
- redis的sort命令
1.简单描述 sort命令可以对list.set和sorted set的元素进行排序,然后显示排序的结果,不影响这些类型里面存储的数据的排序.就是说sort可以对list的元素排序,但是执行lrang ...
- 在Windows上运行Spark程序
一.下载Saprk程序 https://d3kbcqa49mib13.cloudfront.net/spark-2.1.1-bin-hadoop2.7.tgz 解压到d:\spark-2.1.1-bi ...
- Linux主机SSH免密设置解析
为了保证一台Linux主机的安全,所以我们每个主机登录的时候一般我们都设置账号密码登录.但是很多时候为了操作方便,我们都通过设置SSH免密码登录.那么该如何设置?是不是免密码登录就不安全了呢? 一.被 ...
- iOS Block的简单使用以及__block 和static修饰变量
简单的代码总结,不足之处多多指教. //简单的使用 -(void)blockOne{ ; int(^BlockOne)(int) = ^(int num2) { return number*num2; ...