有人曾遇到过的问题,
这次重构爬虫的过程中遇到了一个不小的麻烦,由于FreeBSD-4.11对线程的支持非常不佳(gethostbyname等系统函数不可重入),而使
用多进程又太占内存,所以目标就定在“一个进程多个连接”。没有直接用socket而是用的libcurl中的multi_curl,当然
“select()”还是免不了的。
麻烦很快就来了,建立连接的时候会阻塞在gethostbyname调用上,如果是多进程爬虫这种阻塞只影响一个进程,而现在在多个连接初始化的时候,它浪费的却是大家的时间。
为了让gethostbyname不再阻塞,我们试了dnscache、dnsmasq等DNS缓存软件,但问题还是存在,即对于一些不存在的域名dnscache不缓存,下次解析的时候程序还是会阻塞。这个cache有点名不符实。
折腾了两天后,我们终于采取了最后的方案:把libcurl中调用gethostbyname的函数替换为自己写的一个内存cache,不存在的域名也留记录,免得又阻塞。虽然动作大了点,这最后一招终于起作用了。
但很快发现虽然不阻塞了,但爬取速度连原来的一半都不到,而且如果curl数量太多,它们会都不返回(即用select始终问不到任何结果)。我郁闷之
际,发现这个爬虫程序一跑,机器上的网络操作就无法进行。会不会是机器本身网络就有问题?问了问夏辉,原来开发机有400个连接数的限制。换用专门的测试
机跑了一遍,搞定,速度够快且没有在DNS解析上阻塞。
所以,在写网络爬虫时应该实现自己的DNS缓冲
阅读(2274) | 评论(0) | 转发(0) |