【问题标题】:Nutch FetchData job is too slowNutch FetchData 作业太慢
【发布时间】:2019-08-22 11:42:48
【问题描述】:

我正在使用 Apache Nutch 以编程方式在 EMR 集群中以 6 个周期抓取大约 7000 个 URL(在抓取过程中几乎没有自定义 map-reduce 作业)。 版本是:nutch=v1.15 hadoop=2.7.3 我在具有 20 个 EC2 m4.large 现场实例的 Amazon EMR 集群上运行它。爬取的代码是:

    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 个小时,而且它似乎在等待最后一个映射器完成大约 2.5 个小时(见附件截图)。这项工作可能有什么问题,以及如何加快 FetchData 阶段,也许我可以将其配置为跳过慢速获取器(如果我错过了几个 URL,这不是一个大问题)。

【问题讨论】:

    标签: hadoop mapreduce web-crawler amazon-emr nutch


    【解决方案1】:

    Nutch 的生成器作业按主机(或者域,请参阅partition.url.mode)将获取列表划分为队列。一个获取队列的所有 URL 都在一个 fetcher map 任务中处理,以确保礼貌约束 - 在任何时候只有一个连接到一台主机,并且保证对同一主机的请求之间存在延迟。分区对于性能也很重要,因为 DNS 解析、robots.txt 解析和结果缓存可以在本地地图任务中完成。

    如果一个或几个抓取队列太长或少数抓取的主机响应太慢,这些队列会“阻塞”抓取进度。为了克服这个问题,甚至可以组合使用三个选项:

    1. 使用属性fetcher.timelimit.mins 限制允许获取器映射任务运行的时间。如果达到时间限制,则从提取队列中剩余的 URL 将被跳过并在下一个周期中提取。
    2. 使用generate.max.countgenerate.count.mode 确保没有队列变得太大
    3. (仅当您被允许使用更激进的设置抓取所有主机时)您可以使用更短的抓取延迟 (fetcher.server.delay) 甚至允许并行连接 (fetcher.threads.per.queue)李>

    还有更多选项可以调整爬网的性能,所有属性都记录在文件conf/nutch-default.xml 中。默认值可以很好地确保对一组主机/域的爬网的完整性,并且需要进行更改以在广泛爬网中获得高吞吐量,在这种情况下,某些主机/域不能被彻底爬网。

    【讨论】:

      猜你喜欢
      • 2019-05-29
      • 1970-01-01
      • 1970-01-01
      • 2022-06-26
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2013-09-17
      相关资源
      最近更新 更多