Driver端返回大量结果数据时出现内存不足错误
Driver端返回大量结果数据时出现内存不足错误
现象描述
利用JDBCServer应用,在客户端执行SQL语句。Driver异常退出,在JDBCServer日志中报错信息如下:
2015-11-24 18:29:33,393 ERROR [org.apache.spark.util.Utils] Uncaught exception in thread task-result-getter-3 java.lang.OutOfMemoryError: Java heap space at java.io.ObjectInputStream$HandleTable.grow(ObjectInputStream.java:3469) at java.io.ObjectInputStream$HandleTable.assign(ObjectInputStream.java:3275) at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1674) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1707) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:72) at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:92) at org.apache.spark.scheduler.DirectTaskResult.value(TaskResult.scala:97) at org.apache.spark.scheduler.TaskResultGetter$$anon$2$$anonfun$run$1.apply$mcV$sp(TaskResultGetter.scala:60) at org.apache.spark.scheduler.TaskResultGetter$$anon$2$$anonfun$run$1.apply(TaskResultGetter.scala:51) at org.apache.spark.scheduler.TaskResultGetter$$anon$2$$anonfun$run$1.apply(TaskResultGetter.scala:51) at org.apache.spark.util.Utils$.logUncaughtExceptions(Utils.scala:1701) at org.apache.spark.scheduler.TaskResultGetter$$anon$2.run(TaskResultGetter.scala:50) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
客户端的错误信息如图1:
图1 客户端报的错误

可能原因
分析日志可知,当运行“task-result-getter-3”线程时出现“Out-of-Memory”错误,即表示Driver端获取数据时出现内存不足,导致JDBCServer服务异常。
由于SQL查询的结果数据会返回Driver端,当查询结果数据较大时,会有大量数据返回到Driver。
返回数据的大小的上限由“spark.driver.maxResultSize”配置项控制,当返回结果数据量超过spark.driver.maxResultSize时,Job会抛出异常终止,但不会导致JDBCServer服务异常。在这个问题中,通过查看配置项可知,Driver端的内存为1GB,“spark.driver.maxResultSize”也是1GB,由于Driver进程中还有其他对象占用部分内存,所以在获取的数据量还没有达到“spark.driver.maxResultSize”时,Driver进程内存已经超过1GB从而发生内存溢出,导致JDBCServer服务异常退出。
定位思路
无。
处理步骤
出现该问题,可以通过两种方法修改:增加driver端的内存;控制返回driver端数据的大小。
- 根据具体的应用,修改driver端的内存大小,设置方法有如下两种:
- 在CLASSPATH的“spark-defaults.conf”文件中添加spark.driver.memory 20g。
- 在启动Spark应用时,命令行中添加:–driver-memory 20g。
- 为了减少Driver端出现out-of-memory的错误,您可以适当限制driver端的数据量使其在客户端即报错。 spark.driver.maxResultSize=256m 说明: 建议该配置项的值小于driver端的内存。
- 重新运行Spark应用,如上配置即生效。
参考信息
参考官网http://spark.apache.org/docs/latest/configuration.html,对“spark.driver.maxResultSize”配置项的介绍。