executor 堆外内存
有时候,如果你的 spark 作业处理的数据量特别特别大,比如有几亿数据量,然后spark 作业一运行,时不时的报错,出现 shuffle file cannot find 诸如此类的错误,导致 executor、task lost,out of memory(内存溢出),出现这种情况可能是说 executor 的堆外内存不太够用,导致 executor 在运行的过程中可能会内存溢出,可能导致后续的 stage的task在运行的时候,可能要从一些executor中去拉取shuffle map output文件,但是 executor 可能已经挂掉了,关联的block manager也没有了,所以可能会报 shuffle output file not found;resubmitting task;executor lost 等错误,最后导致 spark 作业彻底崩溃。
上述情况下,就可以去考虑调节一下 executor 的堆外内存。也许就可以避免报错。此外,有时堆外内存调节的比较大的时候,对于性能来说也会带来一定的提升。
调节参数
在 spark-submit
脚本里面用 --conf
的方式添加配置spark.yarn.executor.memoryOverhead
参数,一定要注意!切记不是在 spark 作业代码中用 new SparkConf().set() 这种方式去设置,这种设置是没有用的,一定要在spark-submit
脚本中去设置。默认情况下,这个堆外内存上限大概是300多M,通常项目中真正处理大数据的时候,这里都会出现问题,导致spark作业反复崩溃,无法运行,此时就会去调节这个参数到至少1G,甚至说2G、4G,比如调节为 2G,可以在脚本中加入:
--conf spark.yarn.executor.memoryOverhead=2048
- 1
通常这个参数调节上去以后,就会避免掉某些 JVM OOM 的异常问题,同时会让整体spark作业的性能,得到较大的提升。
连接等待时长
executor 优先从自己本地关联的 BlockManager 中获取某份数据,如果本地 block manager 没有的话,那么会通过 TransferService 去远程连接其他节点上 executor的 block manager 去获取。如果在连接时,正好碰到那个 exeuctor 的 JVM 在垃圾回收,此时就会没有响应,无法建立网络连接,就会卡住,spark 默认的网络连接的超时时长是 60s,如果卡住 60s 都无法建立连接的话,那么就宣告失败了。
如果偶尔碰到一种没有规律情况,突然某某 file uuid(dsfsfd-2342vs–sdf–sdfsd)not found,file lost等,这种情况下,很有可能是有那份数据的executor在jvm gc,所以拉取数据的时候建立不了连接,然后超过默认 60s 以后,直接宣告失败。几次都拉取不到数据的话,可能会导致 spark 作业的崩溃,也可能会导致DAGScheduler 反复提交几次 stage,TaskScheduler 反复提交几次 task,大大延长我们的spark作业的运行时间,此时可以考虑调节连接的超时时长。
spark-submit 脚本中设置
--conf spark.core.connection.ack.wait.timeout=300
- 1
spark.core.connection.ack.wait.timeout
是建立不上连接的时候,超时等待时长,调节这个值比较大以后,通常来说,可以避免部分的偶尔出现的某某文件拉取失败,比如某某文件lost等情况。
总结
之所以讲这两个参数,是因为在真正处理大数据(不是几千万数据量、几百万数据量,而是几亿、几十亿、几百亿的时候)的时候比较实用,很容易碰到executor堆外内存以及gc引起的连接超时的问题,出现file not found,executor lost,task lost等错误,调节上面两个参数还是很有帮助的。
spark-submit 脚本模板:
/usr/local/spark/bin/spark-submit \
--class com.erik.sparkstudy.WordCount \
--num-executors 80 \
--driver-memory 6g \
--executor-memory 6g \
--executor-cores 3 \
--master yarn-cluster \
--queue root.default \
--conf spark.yarn.executor.memoryOverhead=2048 \
--conf spark.core.connection.ack.wait.timeout=300 \
/usr/local/spark/spark.jar \
${1}