【问题标题】:How to make Spark slaves use HDFS input files 'local' to them in a Hadoop+Spark cluster?如何让 Spark 从站在 Hadoop+Spark 集群中使用 HDFS 输入文件“本地”?
【发布时间】:2016-12-24 14:16:15
【问题描述】:

我有一个由 9 台计算机组成的集群,其中安装了 Apache Hadoop 2.7.2 和 Spark 2.0.0。每台计算机都运行一个 HDFS 数据节点和 Spark 从站。其中一台计算机还运行 HDFS 名称节点和 Spark 主节点。

我在 HDFS 中上传了几 TB 的 gz 存档,Replication=2。事实证明,一些档案已损坏。我想找到他们。看起来“gunzip -t”可以提供帮助。因此,我试图找到一种在集群上运行 Spark 应用程序的方法,以便每个 Spark 执行程序测试存档“本地”(即,将其中一个副本位于该执行程序运行的同一台计算机上)到它,只要它是可能的。以下脚本会运行,但有时 Spark 执行程序会处理 HDFS 中的“远程”文件:

// Usage (after packaging a jar with mainClass set to 'com.qbeats.cortex.CommoncrawlArchivesTester' in spark.pom
// and placing this jar file into Spark's home directory):
//    ./bin/spark-submit --master spark://LV-WS10.lviv:7077 spark-cortex-fat.jar spark://LV-WS10.lviv:7077 hdfs://LV-WS10.lviv:9000/commoncrawl 9
// means testing for corruption the gz-archives in the directory hdfs://LV-WS10.lviv:9000/commoncrawl
// using a Spark cluster with the Spark master URL spark://LV-WS10.lviv:7077 and 9 Spark slaves

package com.qbeats.cortex

import org.apache.hadoop.mapred.TextInputFormat
import org.apache.hadoop.io.{LongWritable, Text}
import org.apache.hadoop.mapred.FileSplit
import org.apache.spark.rdd.HadoopRDD
import org.apache.spark.{SparkContext, SparkConf, AccumulatorParam}
import sys.process._

object CommoncrawlArchivesTester extends App {
  object LogAccumulator extends AccumulatorParam[String] {
    def zero(initialValue: String): String = ""
    def addInPlace(log1: String, log2: String) = if (log1.isEmpty) log2 else log1 + "\n" + log2
  }

  override def main(args: Array[String]): Unit = {
    if (args.length >= 3) {
      val appName = "CommoncrawlArchivesTester"
      val conf = new SparkConf().setAppName(appName).setMaster(args(0))
      conf.set("spark.executor.memory", "6g")
      conf.set("spark.shuffle.service.enabled", "true")
      conf.set("spark.dynamicAllocation.enabled", "true")
      conf.set("spark.dynamicAllocation.initialExecutors", args(2))
      val sc = new SparkContext(conf)

      val log = sc.accumulator(LogAccumulator.zero(""))(LogAccumulator)

      val text = sc.hadoopFile(args(1), classOf[TextInputFormat], classOf[LongWritable], classOf[Text])
      val hadoopRdd = text.asInstanceOf[HadoopRDD[LongWritable, Text]]

      val fileAndLine = hadoopRdd.mapPartitionsWithInputSplit { (inputSplit, iterator) =>
        val fileName = inputSplit.asInstanceOf[FileSplit].getPath.toString
        class FilePath extends Iterable[String] {
          def iterator = List(fileName).iterator
        }
        val result = (sys.env("HADOOP_PREFIX") + "/bin/hadoop fs -cat " + fileName) #| "gunzip -t" !

        println("Processed %s.".format(fileName))
        if (result != 0) {
          log.add(fileName)
          println("Corrupt: %s.".format(fileName))
        }
        (new FilePath).iterator
      }

      val result = fileAndLine.collect()

      println("Corrupted files:")
      println(log.value)
    }
  }
}

你有什么建议?


稍后添加:

我尝试了另一个脚本,它通过 textFile() 从 HDFS 获取文件。我看起来像 Spark 执行器在输入文件中不喜欢它的“本地”文件。这与“Spark 将代码带入数据,而不是数据带入代码”不矛盾吗?

// Usage (after packaging a jar with mainClass set to 'com.qbeats.cortex.CommoncrawlArchiveLinesCounter' in spark.pom)
//   ./bin/spark-submit --master spark://LV-WS10.lviv:7077 spark-cortex-fat.jar spark://LV-WS10.lviv:7077 hdfs://LV-WS10.lviv:9000/commoncrawl 9

package com.qbeats.cortex

import org.apache.spark.{SparkContext, SparkConf}

object CommoncrawlArchiveLinesCounter extends App {
  override def main(args: Array[String]): Unit = {
    if  (args.length >= 3) {
      val appName = "CommoncrawlArchiveLinesCounter"
      val conf = new SparkConf().setAppName(appName).setMaster(args(0))
      conf.set("spark.executor.memory", "6g")
      conf.set("spark.shuffle.service.enabled", "true")
      conf.set("spark.dynamicAllocation.enabled", "true")
      conf.set("spark.dynamicAllocation.initialExecutors", args(2))
      val sc = new SparkContext(conf)

      val helper = new Helper
      val nLines = sc.
        textFile(args(1) + "/*").
        mapPartitionsWithIndex( (index, it) => {
          println("Processing partition %s".format(index))
          it
        }).
        count
      println(nLines)
    }
  }
}

SAIF C,你能详细解释一下吗?

【问题讨论】:

  • Spark on Hadoop 可能看不到文件的本地版本。您可能需要在 spark 提交中使用 --files 选项添加它们。使用它时,本地文件将可以通过执行器根目录下的 spark 访问。

标签: scala hadoop apache-spark hdfs cluster-computing


【解决方案1】:

我已经通过从 Spark 的独立模式切换到 YARN 解决了​​这个问题。

相关话题:How does Apache Spark know about HDFS data nodes?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-10
    • 2018-01-14
    • 2019-05-12
    相关资源
    最近更新 更多