使用spark有一段时间了,期间遇到了不少问题,诸如out of memory,java.io.IOException: Filesystem closed,task任务过多导致性能低下等等。现一一列举如下,并给出解决方案。
1. 内存问题,heap error,java.lang.OutOfMemoryError: PermGen space
spark的作业节点有driver和executor,遇到内存问题首先要搞清楚是driver节点还是executor节点。
driver节点的jvm opts可以通过--driver-java-options参数配置,直接通过命令行参数传给SparkSubmit。
executor节点的jvm opts可以通过sparkconf配置,sparkconf.set("spark.executor.extraJavaOptions", ""-Xms1024m -Xmx3072m -XX:MaxPermSize=256m -XX:ThreadStackSize=512"")
2. java.io.IOException: Filesystem closed
把shuffle方式配置成sortshuffle后,数据量加大后时不时会抛出如下错误。
ava.io.IOException: Filesystem closed
org.apache.hadoop.hdfs.DFSClient.checkOpen(DFSClient.java:707)
org.apache.hadoop.hdfs.DFSInputStream.readWithStrategy(DFSInputStream.java:776)
org.apache.hadoop.hdfs.DFSInputStream.read(DFSInputStream.java:837)
org.apache.hadoop.hdfs.DFSInputStream.read(DFSInputStream.java:645)
java.io.DataInputStream.readInt(DataInputStream.java:387)
org.apache.hadoop.hive.ql.io.RCFile$Reader.readRecordLength(RCFile.java:1636)
org.apache.hadoop.hive.ql.io.RCFile$Reader.nextKeyBuffer(RCFile.java:1675)
org.apache.hadoop.hive.ql.io.RCFile$Reader.next(RCFile.java:1842)
org.apache.hadoop.hive.ql.io.RCFileRecordReader.next(RCFileRecordReader.java:161)
org.apache.hadoop.hive.ql.io.RCFileRecordReader.next(RCFileRecordReader.java:148)
org.apache.hadoop.hive.ql.io.RCFileRecordReader.next(RCFileRecordReader.java:46)
org.apache.spark.rdd.HadoopRDD$$anon$1.getNext(HadoopRDD.scala:239)
org.apache.spark.rdd.HadoopRDD$$anon$1.getNext(HadoopRDD.scala:208)
org.apache.spark.util.NextIterator.hasNext(NextIterator.scala:71)
org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:39)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$13.hasNext(Iterator.scala:371)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
org.apache.spark.util.collection.ExternalSorter.insertAll(ExternalSorter.scala:229)
org.apache.spark.shuffle.sort.SortShuffleWriter.write(SortShuffleWriter.scala:74)
仔细排查后发现executor节点因为内存消耗过大,out of memory了。这个问题,一方面要调大executor的内存。另一方面要控制shuffle任务的大小。
3. task数量过多
很多时候如果不去设置partition数量,spark会产生大量的partition。在笔者的测试里,读取hdfs里面总共62个block,spark产生了1800多个partition,导致任务过多,每个任务执行时间只有几百ms。可以通过rdd.coalesce调整partition数量。