Nutch的Hadoop方式爬取效率优化

原文地址:飞船

下面这些是潜在的影响爬取效率的内容(官方资料翻译):

1)DNS设置
2)你的爬虫数量,太多或太少
3)带宽限制
4)每一主机的线程数
5)要抓取的urls的分配不均匀
6) robots.txt中的高爬取延时(通常和urls的分配不均匀同时出现)
7)有很多比较慢的网页(通常和分配不均匀同时出现)
8)要下载太多的内容(PDF,大的html页面,通常和分配不均匀同时出现)
9)其它

那现在怎样改善它们?

1)在每一个本地的爬虫机器上设置DNS,如果是多个爬取机器和一个单独的DNS中心这种情况,那么它就会像有DOS攻击在DNS服务器上那样,使整个系统变慢。我们经常设置两层,首先命中本地DNS缓存,然后就是大的DNS缓存,就像OpenDNS或Verizon。
2)这将是map任务数乘以fetcher.threads.fetch属性值的数量。所以10个map任务*20个线程=一次200个爬取列表。太多的话会超过你系统的负担,太少的话就会使一些机器闲置。你需要认真考虑在你的环境下如何设置这些属性。
3) 带宽限制,用ntop,ganglia和其它监控软件来测定你使用了多少的带宽。计算输入和输出的带宽。可以做一个简单的测试,用抓取网络中一台不用作爬 虫的服务器中,如果它与其中一台爬虫机器连接时或当那台机器抓取时从中下载信息时非常慢,这时你就可以加大带宽。如果你像我后来说的那样设置http的超 时时间并且增加了你的带宽,你会开始看到很多http超时的错误。
4)urls分配的不均匀很有可能是限制性能的一个最大的因素。如果一个线程正 在处理一个网站并且那个网站还有很多url等待抓取,那么其它线程就会闲置直到那个线程完成抓取。一些解决方法是,使用 fetcher.server.delay来缩短网页抓取之间的时间间隔,和使用fetcher.threads.per.host来增加同一网站抓取的 线程数(这仍然在同一个map任务中,因此也是在同一个JVM中的子任务中处理)。如果把这些属性都设置为大于0,你也可以设置 fetcher.server.min.delay属性大于0来设置处理的最小和最大的界限。
5)在一个网站上抓取大量的网页或在少量网站上抓取大量的网页将显著地降低抓取的速度。对于全网爬取,你希望用分布式环境来使所有抓取线程活动。设置generate.max.per.host大于0将限制在同一网站/域名抓取网页的数量
6) 爬取延迟。大多数网站不使用这些设置只有少数使用(一些恶意的网站)。我见过爬取延迟每秒最长延迟2天 的.fetcher.max.crawl.delay属性将忽略爬取延迟大于x的页面。我经常把它设置成10秒,默认是30秒。尽管设置为10秒,如果你 在某个网站上有大量的页面要爬取,但你只能每10秒爬取一个页面,这样也是很慢的。另一方面,把它的值设置过小将忽略该页面并且不抓取这些网页。
7) 有时,网页刚好很慢。设置http.timeout一个低点的值就有助于这种情况。它的默认值为10秒。如果你不在意并想所有网页都尽可能的快,设置得小 点。一些网站。例如digg,会在网站中限制你的带宽并且只允许在某个时间段内存在x个到你机器的连接。所以即使你只在一个网站中爬取50个网页(我仍然 认为太多了)。这样将在每一页面中等待10秒。ftp.timeout也可以用来设置抓取ftp的内容时的时间间隔。
8)大量的内容意味着要降低 抓取的速度。特别是下载PDF或其它非html的文件时。为了避免下载非html的内容,你可以使用url过滤器。我更喜欢prefix和suffix过 滤器。http.content.limit和ftp.content.limit属性可以限制一个文档中下载数据的多少。
9)其它可能导致抓取变慢的因素:
一 台机器最大可打开的socket或文件的多少。你可能会开始看到IO错误或不能打开socket的错误。低效的路由。坏的或家里的路由不能控制同一时间大 量连接的建立。一个错误的路由设置也可能导致问题但这些问题通常很难发现。如果你认为是这个问题,可以用网络跟踪和映射工具来查找。反向的路由则可能是你 网络供应商的问题。坏的网卡。我曾经见过一些网卡突然达到了某个带宽值。这个问题在使用新的网卡时更加普遍。这通常不是我首先想到的但是通常是可能会出现 的。可以使用tcpdump和网络监控

本次优化方向:

A,1)3)为硬件,设置好了以后改变不大。暂不考虑。
B,5)generate.max.per.host暂设置为0。暂不考虑。
C,8)本次爬虫设置只爬取网页内容,不爬媒体文件。
D,2)4)6)7)9)为优化目标


Hadoop配置:

三台:主机内存8G,2台slave内存20G,主从内存配置不合理有一定原因,这里就不再赘述。以后也是一个优化方向

网络带宽:100M

优化前的准备工作:

没有优化之前,种子数量在10条左右的时候,单机版和Hadoop版的爬取效率大约都在2条/秒(包括建立索引)。
优化了Nutch索引,stored和indexed,索引不需要存储的尽量不存储,不需要索引的尽量不索引。并且去掉不必要的索引项目。当种子数增加到40条左右的时候,Hadoop版的爬取效率大约在3.5条/秒。由此确定了种子数量对爬取有影响的优化方向。

参照hadoop的优化方针,做了如下优化:

1,优化系统参数 readahead buffer
blockdev –report
blockdev –setra 1024 /dev/sda
2,优化hadoop参数
hdfs-default
 dfs.namenode.handler.count:20
 dfs.datanode.handler.count:5
 dfs.replication:3
mapred-default.xml
 mapreduce.tasktracker.http.threads:50
 io.sort.factor:20
 mapred.child.java.opts:-Xmx400m
 mapreduce.task.io.sort.mb:200
 mapreduce.map.sort.spill.percent:0.8
 mapreduce.map.output.compress:true
mapreduce.map.output.compress.codec:org.apache.hadoop.io.compress.DefaultCodec     com.hadoop.compression.lzo.LzoCodec为最优
mapreduce.reduce.shuffle.parallelcopies:10

优化开始:

2014/7/9 上午

优化内容

增大种子数:选取的3000左右的有效的国外网站。

yarn-site
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>2048</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>3072</value>
</property>
mapred-site
<property>
<name>mapreduce.map.memory.mb</name>
<value>1536</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>2560</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xms512m -Xmx1024m</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xms1024m -Xmx2048m</value>
</property>
slave
yarn-site
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>3072</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>6144</value>
</property>
mapred-site
<property>
<name>mapreduce.map.memory.mb</name>
<value>4096</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>8192</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xms2048m -Xmx3072m</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xms5120m -Xmx6144m</value>
</property>

结果:

共爬取并建立了91986条solr索引,共耗时22235秒。最终效率:4.14条/秒。

4.136991        
2923 2923 11:06:05 11:20:51 0:14
36538 33615 11:20:51 13:13:38 1:52
68255 31717 13:13:38 15:16:42 2:03
91986 23731 15:16:42 17:16:40 1:59

2014/7/9 下午

优化内容:

nutch-site

<name>fetcher.threads.per.host</name> 5
<name>fetcher.threads.fetch</name>20

结果:


    数
效率 5.38条/秒 全体 Nutch Index                  
总条数 每回条数 开始 终了 耗时 速度 开始 终了 耗时 速度 开始 终了 耗时 速度  
1 2923 2923 18:22:04 18:48:55 1611 1.81 18:22:04 18:35:13 789 3.70 18:37:05 18:48:55 710 4.12
2 36538 33615 18:49:41 20:59:04 7763 4.33 18:49:41 20:20:31 5450 6.17 20:22:18 20:59:04 2206 15.24
3 68255 31717 21:00:11 22:57:35 7044 4.50 21:00:11 22:26:21 5170 6.13 22:28:08 22:57:35 1767 17.95
4 91986 23731 22:59:19 0:58:52 7173 3.31 22:59:19 0:28:49 5370 4.42 0:31:03 0:58:52 1669 14.22
5 115646 23660 1:00:49 2:49:14 6505 3.64 1:00:49 2:19:21 4712 5.02 2:21:19 2:49:14 1675 14.13

结论:

速度从4.14-〉5.38,提升了29.95%。从这一点来看Nutch的fetch线程数目对爬取效率有一定影响。


2014/7/10

优化内容:

根据7/9日的方向,增加fetch线程数。

nutch-site
<property>
  <name>fetcher.threads.fetch</name>
  <value>100</value>
</property>
<property>
 <name>plugin.includes</name>
    <value>protocol-http|urlfilter-regex|parse-html|index-(basic|customized)|indexer-solr|scoring-opic|urlnormalizer-(pass|regex|basic)</value>
</property>
<property>
  <name>indexer.skip.notmodified</name>
  <value>true</value>
  <description>Whether the indexer will skip records with a db_notmodified status.
  </description>
</property>

结果:


    数
效率 6.22条/秒 全体 Nutch Index                  
总条数 每回条数 开始 终了 耗时 速度 开始 终了 耗时 速度 开始 终了 耗时 速度  
1 3014 3014 15:01:01 15:26:07 1506 2.00 15:01:01 15:13:30 749 4.02 15:15:13 15:26:07 654 4.61
2 39069 36055 15:26:54 17:34:55 7681 4.69 15:26:54 17:01:35 5681 6.35 17:03:25 17:34:55 1890 19.08
3 73156 34087 17:35:57 19:33:36 7059 4.83 17:35:57 18:59:06 4989 6.83 19:01:08 19:33:36 1948 17.50
4 103994 30838 19:34:55 21:46:40 7905 3.90 19:34:55 21:03:07 5292 5.83 21:05:31 21:46:40 2469 12.49

结论:

速度从5.38-〉6.22,提升了15.61%。fetch线程数目增加,优化效果在减小。


2014/7/11上午

改变优化方向:

考虑到网速的问题,放弃了用之前有3000左右的有效网站地址的国外新闻网站。改用下列网址http://bj.elanw.com/,由于初始只有一个地址。防止爬取深度过深,先爬去两层然后作为基础,再作爬取。再次爬取的层数为3层。

结果:


    数
效率 11.61条/秒 全体 Nutch Index                  
总条数 每回条数 开始 终了 耗时 速度 开始 终了 耗时 速度 开始 终了 耗时 速度  
1 2830 2830 11:13:05 11:35:52 1367 2.07 11:13:05 11:26:40 815 3.47 11:28:20 11:35:52 452 6.26
2 43885 41055 11:36:51 13:07:01 5410 7.59 11:36:51 12:29:47 3176 12.93 12:31:55 13:07:01 2106 19.49
3 83074 39189 13:08:11 14:27:47 4776 8.21 13:08:11 14:00:53 3162 12.39 14:02:53 14:27:47 1494 26.23

结论:

速度从6.22-〉11.61,提升了86.66%。可见访问网站的速度对爬虫有很大影响。


2014/7/11下午

优化方向:

统计了一下上午爬虫每个阶段的详细数据,结果如下:

Inject Generate Fetch Parse CrawlDB Link inversion Dedup Index Cleanup index
11:13:05 11:14:54 11:16:22 11:21:51 11:23:25 11:24:34 11:26:40 11:28:20 11:35:52
0:01:49 0:01:28 0:05:29 0:01:34 0:01:09 0:02:06 0:01:40 0:07:32 0:00:59
11:36:51 11:36:51 11:38:38 12:11:34 12:21:58 12:23:39 12:29:47 12:31:55 13:07:01
  0:01:47 0:32:56 0:10:24 0:01:41 0:06:08 0:02:08 0:35:06 0:01:10
13:08:11 13:08:11 13:09:56 13:41:31 13:50:56 13:52:27 14:00:53 14:02:53 14:27:47
  0:01:45 0:31:35 0:09:25 0:01:31 0:08:26 0:02:00 0:24:54  

从结果上看:fetch和index所耗时间占每次爬取时间的80%左右,所以重点考虑fetch的参数优化。

另外,察看资料发现之前Nutch的配置有个优化项目设置不对,Nutch1.8中不是fetcher.threads.per.host而是fetcher.threads.per.queue。

优化内容:

<property>
  <name>fetcher.threads.per.queue</name>
  <value>5</value>
</property>
<property>
  <name>fetcher.queue.depth.multiplier</name>
  <value>100</value>
</property>
<property>
  <name>fetcher.server.delay</name>
  <value>2.0</value>
</property>
<property>
  <name>fetcher.server.min.delay</name>
  <value>1.0</value>
</property>

结果:


    数
效率 13.87条/秒 全体 Nutch Index                  
总条数 每回条数 开始 终了 耗时 速度 开始 终了 耗时 速度 开始 终了 耗时 速度  
1 2238 2238 14:38:05 14:56:37 1112 2.01 14:38:05 14:48:07 602 3.72 14:49:43 14:56:37 414 5.41
2 43704 41466 14:57:25 16:21:00 5015 8.27 14:57:25 15:43:12 2747 15.10 15:44:52 16:21:00 2168 19.13
3 82269 38565 16:21:25 17:34:21 4376 8.81 16:21:25 17:04:29 2584 14.92 17:06:24 17:34:21 1677 23.00

结论:

速度从11.61-〉13.87,提升了19.47%。可见fetch的参数优化对整体爬虫效率有不小的影响。


2014/7/11晚上

优化内容:fetch参数

<property>
  <name>fetcher.threads.per.queue</name>
  <value>10</value>
</property>
<property>
  <name>fetcher.queue.depth.multiplier</name>
  <value>200</value>
</property>
<property>
  <name>fetcher.threads.fetch</name>
  <value>200</value>
</property>

结果:


    数
效率 14.52条/秒 全体 Nutch Index                  
总条数 每回条数 开始 终了 耗时 速度 开始 终了 耗时 速度 开始 终了 耗时 速度  
1 2224 2224 18:07:04 18:23:59 1015 2.19 18:07:04 18:16:33 569 3.91 18:18:07 18:23:59 352 6.32
2 42079 39855 18:24:46 19:35:45 4259 9.36 18:24:46 19:07:15 2549 15.64 19:09:02 19:35:45 1603 24.86
3 83466 41387 19:36:47 20:46:35 4188 9.88 19:36:47 20:20:37 2630 15.74 20:22:24 20:46:35 1451 28.52

结论:

速度从13.87-〉14.52,提升了4.69%。可见fetch的参数优化对整体爬虫效率有影响,但效果已经减小


总结:

通过这几天的优化,使得爬虫效率从4.14条/秒提升到了14.52条/秒,速度提升250.72%

1,Nutch爬虫整体过程中,fetch和index创建占据着整体爬取时间的80%左右,fetch:55%,index:35%

   fetch方面主要考虑参数优化,nutch1.8种有10多个参数,上述已经做了部分优化。
    index创建的优化主要考虑做solr集群,现在还是单机版。是今后的优化方向

2,Hadoop的相关优化,要事先做完,特别是虚拟内存和物理内存的优化,否则在优化1时会出现内存溢出,IO异常等错误

3,爬取网站的访问速度对爬虫效率有很大影响,这个很容易理解

4,从每次爬虫的速度来看,种子数量对爬虫速度有很大的影响爬虫官方目标是每个月几十亿,暂算30亿的话,每天1亿网页爬取量来算,每秒要爬取1100多网页。如果其他因素都很理想得状态下,种子数量的多少对爬虫速度有非常大的影响实际实践效率数据:每天200万网页,每秒20多条网页。

 

Tagged on: , ,

发表评论

电子邮件地址不会被公开。 必填项已用*标注