我有用C#写的网络爬虫,它使用多线程。目前,它可以下载和解析大约1000个链接/分钟,但当我运行ex。3个实例同时,每个实例可以达到1000个链接/分钟,所以我有3000个链接/分钟。一个实例使用高达2%的CPU,100MB内存,1%的网络速度。现在我想知道,当我有可用的资源(cpu,ram,网络)时,一个实例是否有可能达到3000个链路/分钟或更多?
我的代码结构:
ThreadSafeFileBuffer<string> successWriter = new ThreadSafeFileBuffer<string>("ok.txt");
IEnumerable<string> lines = File.ReadLines("urls.txt");
var options = new ParallelOptions
{
CancellationToken = _cts.Token,
MaxDegreeOfParallelism = 500
};
Parallel.ForEach(lines, options, (line, loopState, idx) =>
{
var crawler = new Crawler(line);
var result = crawler.Go(); //download,parse
successWriter.AddResult(result);
}我有Windows 7,CPU i7,16 RAM,固态硬盘
发布于 2013-10-22 06:08:00
在URL列表上使用Parallel.ForEach的问题是,这些列表通常包含来自同一站点的许多URL,并且您最终会收到对同一站点的多个并发请求。一些网站对此不以为然,会阻止你或插入人为的延迟。
每分钟1,000个请求相当于每秒16或17个请求,这几乎是您在不采取非常措施的情况下所能做的极限。很大一部分问题是DNS解析,这可能需要相当长的时间。此外,默认的.NET ServicePointManager将任何给定站点上的并发请求限制为2个。如果您希望支持更多内容,则需要更改ServicePointManager.DefaultConnectionLimit属性。
你肯定不想添加成百上千的线程。我也这么做过一次。这是痛苦的。您需要的是一些能够非常快速地发出异步请求的线程。我的测试表明,单个线程每秒不能支持超过15个请求,因为HttpRequest.BeginGetResponse在异步之前做了大量的同步工作。正如文档所述:
在BeginGetResponse方法变为异步之前,此方法需要完成一些同步设置任务(例如,
解析、代理检测和TCP连接)。
您可以通过增加DNS客户端缓存的大小并在单独的计算机上使用本地DNS缓存来提高速度,但在那里所能实现的功能是有限的。
我不知道你做了多少爬行。如果你正在做很多事情,那么你需要实现一个礼貌策略,考虑到robots.txt文件,限制它访问特定站点的频率,限制它下载的URL类型(例如,如果你不能用MP3或.doc文件做任何事情,下载它是没有用的),等等。为了防止你的爬虫被阻止,你的爬虫成为核心的礼貌策略执行者,只是碰巧下载网页。
我一段时间以前就开始写这方面的文章,但后来没有写完(其他项目优先)。第一篇帖子和其他帖子的链接请参见http://blog.mischel.com/2011/12/13/writing-a-web-crawler-introduction/。另请参阅http://blog.mischel.com/2011/12/26/writing-a-web-crawler-queue-management-part-1/。这是我一直想要回到的东西,但几乎两年后我仍然没有成功。
您还将遇到proxy problems、网址过滤问题(here和here)、weird redirects和asynchronous calls that aren't completely asynchronous。
发布于 2013-10-21 20:45:34
您不需要更多的线程,因为这些线程都在等待。你需要一个异步程序,它不会阻塞等待web回复的线程。
线程的问题是它们是一种相当昂贵的资源,因为它们的堆栈需要内存,并且它们为OS线程调度程序创建了工作。在你的程序中,这个调度程序不断地切换线程,以便它们都能轮流等待。但是他们没有做任何有用的事情。
发布于 2013-10-21 20:24:20
是的,是这样的。找出您的瓶颈所在,并提高性能。
编辑:
如果您使用的是Parallel.ForEach,则可以使用ParallelOptions参数尝试重载。设置MaxDegreeOfParallelism属性可能会有所帮助。
https://stackoverflow.com/questions/19494391
复制相似问题