nutch fetchdata作业太慢

k4ymrczo  于 2021-05-29  发布在  Hadoop
关注(0)|答案(1)|浏览(296)

我使用apachenutch以编程方式在emr集群中以6个周期对大约7000个url进行爬网(在爬网过程中几乎没有定制的map reduce作业)。版本是:nutch=v1.15 hadoop=2.7.3我在amazonemr集群上运行它,有20个ec2 m4.1大型spot示例。爬网的代码是:

public crawl(Folder seeds, Folder output) 
        throws IOException, InterruptedException {
        final Folder crawldb = output.folder("crawldb");
        try {
            new Injector(this.conf).inject(
                crawldb.path(), seeds.path(),
                true, true
            );
        } catch (final ClassNotFoundException err) {
            throw new IOException("Failed to inject URLs", err);
        }
        final Folder segments = output.mkdir("segments");
        // cycles = 6 in my case
        for (int idx = 0; idx < cycles; ++idx) {
            this.cycle(crawldb, segments);
        }
    }

    private void cycle(final Folder crawldb, final Folder segments)
        throws IOException, InterruptedException {
        try {
            Logger.info(this, "Generating...");
            // configured as 1_000_000 in EMR cluster
            final int topn = this.conf.getInt("yc.gen.topn", 1000);
            // configured as 40 (2 x slave_nodes) in EMR cluster
            final int nfetch = this.conf.getInt("yc.gen.nfetch", 1);
            new Generator(this.conf).generate(
                crawldb.path(),
                segments.path(),
                nfetch, topn, System.currentTimeMillis()
            );
            // the latest segment
            final Optional<Folder> next = Batch.nextSegment(segments);
            if (next.isPresent()) {
                final Path sgmt = next.get().path();
                Logger.info(this, "Fetching %s...", sgmt);
                new Fetcher(this.conf).fetch(
                    // @checkstyle MagicNumber (1 line)
                    sgmt, 10
                );
                Logger.info(this, "Parsing %s...", sgmt);
                new ParseSegment(this.conf).parse(sgmt);
            }
            new CrawlDb(this.conf).update(
                crawldb.path(),
                // all segments paths
                segments.subfolders().stream()
                    .toArray(Path[]::new),
                true, true
            );
        } catch (final ClassNotFoundException err) {
            throw new IOException(
                "Failed to generate/fetch/parse segment", err
            );
        }
    }

当我用7000个种子url和6个运行周期运行它时,nutch会变得非常慢 FetchData 工作:它运行了大约3个小时,它似乎是等待最后一个Map完成约2.5个小时(见截图附件)。这项工作可能有什么问题以及如何加快fetchdata阶段的速度,也许我可以将其配置为跳过缓慢的fetcher(如果我错过几个url,这不是一个大问题)。

9cbw7uwe

9cbw7uwe1#

nutch的generator作业按主机将fetch列表划分为队列(或者域,请参阅 partition.url.mode ). 一个回迁队列的所有URL都在一个回迁Map任务中处理,以确保礼貌约束—任何时候只有一个到一个主机的连接,并且到同一主机的请求之间保证有延迟。分区对于性能也很重要,因为dns解析、robots.txt解析和结果缓存可以在Map任务中本地完成。
如果一个或几个获取队列太长或几个已爬网的主机响应太慢,这些队列将“阻止”爬网进程。为了克服这个问题,有三种选择甚至可以结合起来:
限制允许使用属性运行获取程序Map任务的时间 fetcher.timelimit.mins . 如果达到时间限制,则将跳过获取队列中的剩余URL,并在下一个周期中获取。
确保没有队列过大 generate.max.count 以及 generate.count.mode (仅当允许使用更具攻击性的设置对所有主机进行爬网时)可以使用更短的爬网延迟( fetcher.server.delay )甚至允许并联( fetcher.threads.per.queue )
有更多的选项来优化爬网的性能,所有属性都记录在文件中 conf/nutch-default.xml . 默认值可以确保仅限于一组主机/域的爬网的完整性,并且需要更改以在广泛的爬网中获得高吞吐量,在这种情况下,某些主机/域不能完全爬网。

相关问题