我曾经在.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操作?