【经验总结】.Net的并发连接数限制问题

  最近在项目中遇到了很棘手的问题,查到最后发现是由于HttpWebRequest对于同一个domain的请求建立的连接数同时不能超过两个的限制造成的。我用这篇短文把对这个问题的处理记录下来,同时也做为个人的经验积累吧,希望对大家有所帮助。

  这里所说的连接并发数限制是指对于同一个domain发起的最大连接数。其实在大多数微软的产品或组件中都存在这个限制,一般这个数值是2/4个,也就是说在默认情况下,对于同一个domain同时最多有两个连接处于建立状态。例如:熟悉javascript编程的人可能很清楚这个限制,在使用ajax时创建XmlHttpRequest对于同一个domain就有这个限制,实际上这个限制是继承与微软的IE浏览器的默认限制,也就是说IE浏览器本身对于同一个domain发起的连接数同时最多存在两条链路,由于Http协议是一个无状态的协议,连接也在Response返回来以后断掉(除非指定了keep-alive可以保持连接,这样可以保持一段时间),当然对于像IE这种多模式的客户端来说,这两条连接同时建立的时候几乎很少,甚至不可能,当然在comet技术应用时是很模拟。所以对于这种模式下的客户端来说这个连接限制没有那么明显,甚至很多人都不知道这个限制的存在。当然微软做这个限制是道理的,我想最大的好处可能就是防止一个客户端发起太多的并行连接来攻击服务器了(我的拆测)。但是这个连接限制在同时也阻碍了单模式下的服务器编程,当然我们可以修改这个默认值,但是毕竟还是比较麻烦。而且这个修改对于一个应用程序来说来说是全局的(我采取的方式,因为对HttpWebRequest对象的修改并不适合我的项目),当然这个修改也可以针对具体的HttpWebRequest对象进行设置。具体如何修改可以参照一下这篇文章http://www.qqdao.org/Lists/Posts/Post.aspx?List=751e96b2%2D405a%2D41cf%2Dadce%2Dc6a5b9a8c157&ID=22&RootFolder=%2A

  我的问题是出现在刚刚上线的项目中,我的这个项目是一个服务器端程序,内部使用了HttpWebRequest去请求一个网站的url。在这个项目中请求的次数非常频繁。

  问题表现:刚上线的服务就要承担很大的压力,据统计大概每秒钟有至少2000多个请求需要处理,有四台服务器做负载实现。但是发现在功能环境下运行很好的程序到了生产环境很多调用都失败了,成功的占了比例不大。失败的请求大都报如下错误“System.Net.WebException: The request was aborted: The request was canceled.”。但是查看网站的压力并不大,可以说是很轻,在用netstat -abn | find "xxxx"命令查看到网站的连接,发现只有两个已经建立的连接,当然这两个连接是并行的,并且是keep-alive的连接。从问题可以看出,大多数请求实际上是发送失败了,之后被取消了。但是这个发送失败并不是网站一侧没有资源来应答,而是请求在客户端就没有发出去数据包,可以说请求本身就没有发送出去。这个问题导致网站对于请求的吞吐能力再强也没有用,客户端请求发送失败。给人的感觉就像请求积压很厉害并且最后放弃了。

  问题排查:这个问题对于没有经验的人来说却实无从下手,方法就是尽量排除一些可能的原因,剩下最后的几个原因时进行验证。首先我猜测可能是线程池中的线程用尽了,但是后来抓了dump进行分析发现并不是这个原因。在经过一个晚上沉重的思考以后,第二天早上似乎有了一点灵感,已经很确定是由于连接数的限制了。我这样说是因为我考虑到网站端如果长时间没有返回,那么这个连接就一直在占用,当两个连接都在被占用时,再发送请求是就会由于没有及时得到可用的连接而失败(虽然实际情况可能比这要复杂的多,例如缓存请求,进行重试等,但是请求很频繁是,发送的能力是有限的,总会有一些请求没有及时发送出去而抛出异常,这个问题就好比通过一个漏斗向一个容器中注入水一样,如果流入的速度大于流出的速度会使漏斗慢慢达到盛满水,这样再继续时肯定就会流到外面了,也就是这里出现了异常,也就是多出来的会放舍弃掉。

  问题解决:既然知道了原因,那么解决起来自然也就比较容易了,修改.Net的这个默认并发连接数可以通过很多种方式,可以通过在程序初始化时执行以下代码完成ServicePointManager.DefaultConnectionLimit = 500;,也可以通过修改配置文件来达到同样的效果,由于程序已经上线,所以我是通过修改配置完成的。这个东西自然在线下也做了很多测试,发现确实是这里的问题,于是晚上做了一个更新,第二天早上发现基本所有调用都成功了,不成功的也是网站没有返回结果超时导致的,真是庆幸。同时发现以前经常报的错也不见了,正如我所料。当然我这限制设置为500而没有设置到1000主要是我想客户端的端口开的不会太多。

  总结:这个配置我觉得是一个限制,不能设置的太大也不能太小。其实搞计算机的需要很多经验的同时,灵感也很重要,这个问题就是我在当天晚上没有办法的情况下入睡以后,第二天醒来以后突然觉察到的,之后到了公司就开始测试和验证,没想到还真解决了问题,但是有一点还是特别提醒,无论是用什么协议栈发送调用或消息,最好都不要使用for语句压消息,这会太调用量大时会出现问题。

  

【作者】: GUO Xingwang
【来源】: http://thriving-country.cnblogs.com/ 
     本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
1
0
(请您对文章做出评价)
« 上一篇: 大家一起学面向对象设计模式系列Chapter 04 建造者(Builder)
» 下一篇: 【经验总结】服务器端编程部分概念理解
posted @ 2009-12-18 22:03 GUO Xingwang 阅读(1859) 评论(13)   编辑 收藏 网摘 所属分类: .Net Framework, C#, 总结

 

   回复   引用   查看     
#1楼 2009-12-18 22:16 | shawnliu       
并发显然应该是浏览器的设置了
你应该可以修改浏览器并发数的啊

   回复   引用   查看     
#2楼 2009-12-18 22:39 | cokkiy       
Net的并发连接数限制问题
------------------
Lz,这不是Net的并发连接数限制问题,而是标准要求web 浏览器不能同时发起超过2个连接到同一个web服务器
不过现在许多浏览器都不遵守这个标准了,比如天天喊自己很标准的FF,Chorme之流

   回复   引用   查看     
#3楼 2009-12-18 22:48 | 亚历山大同志       
自己实现http请求不就完了
   回复   引用   查看     
#4楼 2009-12-18 22:52 | Jeffrey Zhao       
不是吧,我经常写程序抓过很多东西,没有遇到过这个问题。
2个连接限制是HTTP协议要求的,HttpWebRequest没有必要遵守……
打个比方,如果用C#实现一个浏览器,一个进程n各tab,只是每个tab分别有限制。
你说的ServicePointManager.DefaultConnectionLimit是对的,不过你原因找错了。

   回复   引用   查看     
#5楼 2009-12-18 22:58 | 记账本       
这一句的位置 有没有要求?能说说具体加在哪里吗?
ServicePointManager.DefaultConnectionLimit = 500;

   回复   引用   查看     
#6楼 [ 楼主]2009-12-18 23:07 | GUO Xingwang       
@Jeffrey Zhao
感谢老赵指点。最近要绩效考核了,老板说要这个季度发三篇文,我赶紧补呢。

   回复   引用   查看     
#7楼 [ 楼主]2009-12-18 23:14 | GUO Xingwang       
@记账本
帅哥,我把它加到程序启动时了

   回复   引用   查看     
#8楼 2009-12-18 23:31 | Gray Zhang       
这不是.NET的限制,这是HTTP协议的限制
   回复   引用   查看     
#9楼 2009-12-19 11:29 | ilovedotnet       
.NET好可怜,背了好多黑锅啊,哈哈!
   回复   引用   查看     
#10楼 2009-12-20 01:38 | skyaspnet       
您好,想请教一个连接问题,比如说现在有个网站,用户要进行AJAX投票操作,如果同时发起2个连接,但是不止一个用户,那服务器是不是只能同时处理两个连接,其他用户的连接都根本发送不到服务器?还是说服务器针对每个用户的同时连接数限制是2个?可以同时处理多个用户的不同连接请求?

谢谢!

   回复   引用   查看     
#11楼 [ 楼主]2009-12-20 13:20 | GUO Xingwang       
@skyaspnet
这个限制完全是客户端的限制,和服务器应该没有关系。服务端的能力自然是很强的。哈哈

   回复   引用   查看     
#12楼 2009-12-20 17:59 | skyaspnet       
@GUO Xingwang
感谢您的回复:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值