Spark on Yarn 为什么出现内存超界container被kill

一个Executor对应一个JVM进程。 从Spark的角度看,Executor占用的内存分为两部分:ExecutorMemoryMemoryOverhead。其中,ExecutorMemory为JVM进程的Java堆区域,MemoryOverhead为JVM进程中除Java堆以外占用的空间大小,包括方法区(永久代)、Java虚拟机栈、本地方法栈、JVM进程本身所用的内存、堆外内存(Direct Memory)等。

spark.driver.memoryspark.executor.memory 分别设置Spark的Driver和Executor的ExecutorMemory.

spark.yarn.executor.memoryOverheadspark.yarn.driver.memoryOverhead分别设置Spark的Driver和Executor的MemoryOverhead.

另外,Spark会大量分配堆外内存,堆外内存默认最大可以和ExecutorMemory一样,可以通过javaOptions使用MaxDirectMemorySize配置最大值。

堆外内存最大可以和ExecutorMemory一样,但是堆外内存又受MemoryOverhead限制,所以当MaxDirectMemorySize,ExecutorMemoryMemoryOverhead设置不合理时,会出现container内存超限,被Yarn kill的情况。

比如,ExecutorMemory 为8G,MemoryOverhead为4G,MaxDirectMemorySize没有设置,此时yarn认为一个container最大可以使用12G内存,但是堆外内存最大可以使用8G,导致container最大可以使用超过16G内存(堆内内存+ 堆外内存),比12G大, 最终被Yarn kill掉。

合理的设置规则为: ExecutorMemory + MemoryOverhead > ExecutorMemory + MaxDirectMemorySize

所以,Spark应用占用集群内存的总大小为:

(executor个数) * (SPARK_EXECUTOR_MEMORY+ spark.yarn.executor.memoryOverhead)+(SPARK_DRIVER_MEMORY+spark.yarn.driver.memoryOverhead)

参数调优建议:

每个Executor进程的内存设置4G~8G较为合适。

每个Executor的CPU core数量设置为2~4个较为合适。

以下是部分建议的参数设置:

--conf "spark.driver.extraJavaOptions=-XX:MaxDirectMemorySize=1024m -Xmn4g -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/tmp/log/run/gc-%t.log" \

--conf "spark.speculation=true" \
--conf "spark.speculation.quantile=0.95" \

--conf "spark.kryoserializer.buffer.max=1024m" \

--conf "spark.sql.hive.metastorePartitionPruning=true" \
--conf "spark.sql.optimizer.metadataOnly=true" \
--conf "spark.sql.parquet.filterPushdown=true" \
--conf "spark.sql.hive.caseSensitiveInferenceMode=NEVER_INFER" \
--conf "spark.sql.hive.convertMetastoreParquet=false" \

    原文作者:这个该叫什么呢
    原文地址: https://www.jianshu.com/p/ceee2d5990f8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞