Mor*_*eng 9 .net c# sockets stream web-crawler
我曾经在.NET中编写了一个Crawler.为了提高其可伸缩性,我尝试利用.NET的异步API.
System.Net.HttpWebRequest具有异步API BeginGetResponse/EndGetResponse.但是,这对API只是为了获取HTTP响应头和Stream实例,我们可以从中提取HTTP响应内容.所以,我的策略是使用BeginGetResponse/EndGetResponse来异步获取响应Stream,然后使用BeginRead/EndRead从响应Stream实例异步获取字节.
在Crawler进行压力测试之前,一切看起来都很完美.在压力测试下,Crawler遭受高内存使用.我用WinDbg + SoS检查了内存,并说明System.Threading.OverlappedData实例有很多字节数组.经过一些互联网搜索后,我从微软发现了这个KB http://support.microsoft.com/kb/947862.
根据KB,异步I/O的数量应该具有"上限",但它不会告诉"建议的"绑定值.所以,在我看来,这个KB没有任何帮助.这显然是一个.NET错误.最后,我不得不放弃从响应Stream中异步提取字节的想法,而只是以同步方式进行.
允许带有点网络套接字的异步IO的.NET库(Socket.BeginSend/Socket.BeginReceive/NetworkStream.BeginRead/NetworkStream.BeginWrite)必须具有其异步IO的未完成缓冲区(发送或接收)数量的上限.
网络应用程序应该具有其发布的未完成异步IO 数量的上限 .
编辑:添加一些问号.
任何人都有在Socket和NetworkStream上进行异步I/O的经验吗?一般来说,生产中的爬虫是否通过同步或异步的互联网进行I/O操作?
Han*_*ant 11
Hmya,这不是.NET框架问题.链接的知识库文章本来可能更明确一点:"你正在使用加载的枪,当你瞄准你的脚时就会发生这种情况".该枪中的子弹是.NET,使您能够启动尽可能多的异步I/O请求.它会做你要求它做的事情,直到你遇到某种资源限制.在这种情况下,可能在第0代堆中有太多固定的接收缓冲区.
资源管理仍然是我们的工作,而不是.NET.它与没有绑定的内存分配没有什么不同.解决此特定问题需要限制未完成的BeginGetResponse()请求的数量.有数百个没有意义,他们每个人都必须一次挤过Intertube.添加另一个请求只会导致完成时间更长.或者崩溃你的程序.
显然,无论您的爬虫是同步/异步,您都希望限制并发请求的数量。这个限制不是固定的,它取决于你的硬件、网络……
我不太确定你的问题是什么,因为 HTTP/Sockets 的 .NET 实现是“ok”。有一些漏洞(请参阅我关于正确控制超时的文章),但它完成了工作(我们有一个每秒获取数百页的生产爬虫)。
顺便说一句,我们使用同步 IO,只是为了方便起见。每个任务都有一个线程,我们限制并发线程的数量。对于线程管理,我们使用Microsoft CCR。
归档时间: |
|
查看次数: |
4860 次 |
最近记录: |