Apache spark sc.wholeTextFiles+toDebugString即使在执行操作之前也需要很长时间

Apache spark sc.wholeTextFiles+toDebugString即使在执行操作之前也需要很长时间,apache-spark,Apache Spark,下面是一个简单的代码段 inputForCust是14762个文件,总计57M,平均文件大小为0.5K。这些文件是从通过NFS装载的本地文件系统加载的 val inputCustFiles = sc.wholeTextFiles(inputForCust, jobArgs.minPartitions) println("This prints immediately") inputCustFiles.toDebugString println("This prints after 20 mins

下面是一个简单的代码段

inputForCust是14762个文件,总计57M,平均文件大小为0.5K。这些文件是从通过NFS装载的本地文件系统加载的

val inputCustFiles = sc.wholeTextFiles(inputForCust, jobArgs.minPartitions)
println("This prints immediately")
inputCustFiles.toDebugString
println("This prints after 20 mins")
inputCustFiles.count
println("This prints after 10 mins")
注意:在整个letextfile之后,我们进行了一些复杂的转换,时间花在了reduceByKey上!!!我简化了代码,只是为了重现问题

我的问题是,为什么inputCustFiles.toDebugString要花这么多时间

如果inputCustFiles.count需要时间,我可以确信它将利用集群处理能力。但是inputCustFiles.toDebugString正在阻止驱动程序

在20分钟的时间内,我在spark UI中没有看到任何活动

如果启用跟踪级别日志记录,我会看到以下几行

[error] [17/03/17 23:23:27] [DEBUG] BlockManager: Getting local block broadcast_1
[error] [17/03/17 23:23:27] [DEBUG] BlockManager: Level for block broadcast_1 is StorageLevel(true, true, false, true, 1)
[error] [17/03/17 23:23:27] [DEBUG] BlockManager: Getting block broadcast_1 from memory
[error] [17/03/17 23:23:43] [TRACE] HeartbeatReceiver: Checking for hosts with no recent heartbeats in HeartbeatReceiver.
[error] [17/03/17 23:24:43] [TRACE] HeartbeatReceiver: Checking for hosts with no recent heartbeats in HeartbeatReceiver.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
任何想法,如果我做错了什么,或者这是spark的限制/缺陷/设计

注:

我们使用的是1.6.2。 如果输入文件的数量发生更改,则删除BugString所需的时间将增加!!! 下面是阻止驱动程序时的堆栈跟踪

java.io.FileInputStream.readBytes(Native Method)
java.io.FileInputStream.read(FileInputStream.java:255)
java.io.BufferedInputStream.read1(BufferedInputStream.java:284)
java.io.BufferedInputStream.read(BufferedInputStream.java:345)
sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
java.io.InputStreamReader.read(InputStreamReader.java:184)
java.io.BufferedReader.fill(BufferedReader.java:161)
java.io.BufferedReader.read1(BufferedReader.java:212)
java.io.BufferedReader.read(BufferedReader.java:286)
org.apache.hadoop.util.Shell$ShellCommandExecutor.parseExecResult(Shell.java:602)
org.apache.hadoop.util.Shell.runCommand(Shell.java:446)
org.apache.hadoop.util.Shell.run(Shell.java:379)
org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:589)
org.apache.hadoop.util.Shell.execCommand(Shell.java:678)
org.apache.hadoop.util.Shell.execCommand(Shell.java:661)
org.apache.hadoop.fs.FileUtil.execCommand(FileUtil.java:1097)
org.apache.hadoop.fs.RawLocalFileSystem$RawLocalFileStatus.loadPermissionInfo(RawLocalFileSystem.java:567)
org.apache.hadoop.fs.RawLocalFileSystem$RawLocalFileStatus.getPermission(RawLocalFileSystem.java:542)
org.apache.hadoop.fs.LocatedFileStatus.<init>(LocatedFileStatus.java:42)
org.apache.hadoop.fs.FileSystem$4.next(FileSystem.java:1815)
org.apache.hadoop.fs.FileSystem$4.next(FileSystem.java:1797)
org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus(FileInputFormat.java:267)
org.apache.hadoop.mapreduce.lib.input.CombineFileInputFormat.getSplits(CombineFileInputFormat.java:217)
org.apache.spark.rdd.WholeTextFileRDD.getPartitions(WholeTextFileRDD.scala:49)
org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:239)
org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:237)
scala.Option.getOrElse(Option.scala:121)
org.apache.spark.rdd.RDD.partitions(RDD.scala:237)
org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:35)
org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:239)
org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:237)
scala.Option.getOrElse(Option.scala:121)
org.apache.spark.rdd.RDD.partitions(RDD.scala:237)
org.apache.spark.rdd.RDD.firstDebugString$1(RDD.scala:1747)
org.apache.spark.rdd.RDD.toDebugString(RDD.scala:1781)
oculus.storeonce.spark.Test$.main(Test.scala:11)
oculus.storeonce.spark.Test.main(Test.scala)

事实证明,spark驱动程序遍历文件系统并获取大量元数据,这样它就可以创建适当大小的正确数量的分区。由于文件系统甚至HDF都不能有效地处理小文件,因此扫描文件系统中的元数据会导致延迟

为什么是rdd,reduceByKey。。。或者rdd.toDebugString正在调用操作,而不是sc.wholeTextFiles/textFiles或rdd.map仍然是一个问题


解决方案/解决方法是将数据存储在类似kafka/cassandra的文件中,或者将多个文件的内容合并到单个文件中。

奇怪的事情