文章目录

  • 1.YARN关键参数配置
  • 1.1 yarn中单个nodemanager控制container的个数
  • 1.2 resourceManager
  • 1.3 executor堆外内存
  • 2.YARN内存参数计算实例
  • 2.1 SPARK ON YARN-CLUSTER
  • 2.2 SPARK ON YARN-CLIENT
  • 3. spark on yarn内存申请
  • 3.1 yarn两个默认内存参数
  • 3.2 spark
  • 3.3 yarn对spark任务内存的申请计算方式
  • 3.3.1 executer使用的内存计算
  • 3.3.2 driver的内存计算


1.YARN关键参数配置

1.1 yarn中单个nodemanager控制container的个数

(1)yarn.nodemanager.resource.memory-mb
作用:该节点分配nodemanager的资源
该节点最大内存划分出来的给nodemanager使用的内存,若物理内存128G,80%可使用,则内存则配置128*0.8,默认是8G,若可用小于8G,则需要修改。
(2)yarn.nodemanager.vmem-pmem-ratio
作用:虚拟内存的比例,默认是2.1,即每使用1G物理内存,分配2.1的虚拟内存

1.2 resourceManager

(1)yarn.scheduler.minimum-allocation-mb
作用:单个容器(container)可申请的最小资源,影响到单个节点的container的数量
(2)yarn.scheduler.maximum-allocation-mb
作用:单个容器(container)可申请的最大内存资源,应用在运行时申请的内存不能超过这个配置项值

1.3 executor堆外内存

spark.yarn.executor.memoryOverhead

作用:executor执行的时候,用的内存可能会超过executor-memoy,所以会为executor额外预留一部分内存。spark.yarn.executor.memoryOverhead代表了这部分内存。这个参数如果没有设置,会有一个自动计算公式(位于ClientArguments.scala中),

其中,MEMORY_OVERHEAD_FACTOR默认为0.1,executorMemory为设置的executor-memory, MEMORY_OVERHEAD_MIN默认为384m。参数MEMORY_OVERHEAD_FACTOR和MEMORY_OVERHEAD_MIN一般不能直接修改,是Spark代码中直接写死的。该参数可以通过 submit脚本进行配置

--conf spark.yarn.executor.memoryOverhead=2048

2.YARN内存参数计算实例

以spark自带的实例SparkPi 为示例:

yarn的资源配置参数如下:

<property>
       <name>yarn.nodemanager.resource.memory-mb</name>
       <value>12288</value>
    </property>
    <property>
       <name>yarn.scheduler.minimum-allocation-mb</name>
       <value>1024</value>
    </property>
    <property>
       <name>yarn.scheduler.maximum-allocation-mb</name>
       <value>10240</value>
    </property>

2.1 SPARK ON YARN-CLUSTER

SPARKPI提交的命令如下

./spark-submit --class org.apache.spark.examples.SparkPi \
    --master yarn-cluster  \
    --num-executors 3 \
    --driver-memory 2g \
    --executor-memory 1g \
    --executor-cores 2 \
     /home/hdfs/spark-2.4.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.4.0.jar \
    200000

本次运行的driver端的2g,3个executeor每个executor1g,在yarn中的申请的资源情况如下图,申请了4container,共申请了9个G的内存:

yarn分配内存 yarn am内存_yarn

yarn-cluster计算公式:
(spark-memory+executor.memoryOverhead)/minimum-allocation-mb*num-executors+(driver-memory+driver.memoryOverhead)/minimum-allocation-mb

total memory = (executor-memory + spark.yarn.executor.memoryOverhead) * num-executors + (spark.driver.memory + spark.yarn.am.memoryOverhead)

spark.yarn.executor.memoryOverhead由于是默认值,spark.yarn.executor.memoryOverhead的默认值计算公式如下,

即spark.yarn.executor.memoryOverhead=max(1024*0.1,384)=384M:

executor计算与yarn-client的计算方式一致,(1024+384)按照1g取整为2g,3个executor的内存为6G

driver内存计算为:ceil((2048+384)/1024)=3g

因此yarn-client的申请内存为:ceil((1024+384)/1024)*3 +ceil((2048+384)/1024)=9G

2.2 SPARK ON YARN-CLIENT

SPARKPI的提交代码如下

./spark-submit --class org.apache.spark.examples.SparkPi \
    --master yarn-client  \
    --num-executors 3 \
    --driver-memory 2g \
    --executor-memory 1g \
    --executor-cores 2 \
     /home/hdfs/spark-2.4.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.4.0.jar \
    200000

本次运行的driver端的2g,3个executeor每个executor1g,在yarn中的申请的资源情况如下图,申请了4container,共申请了7个G的内存:

yarn分配内存 yarn am内存_大数据_02

yarn-client计算公式:

total memory = (executor-memory + spark.yarn.executor.memoryOverhead) * num-executors + (spark.yarn.am.memory + spark.yarn.am.memoryOverhead)

spark.yarn.executor.memoryOverhead由于是默认值,spark.yarn.executor.memoryOverhead的默认值计算公式如下,

即spark.yarn.executor.memoryOverhead=max(1024*0.1,384)=384M:

max(executor-memory*0.1,384)

由于yarn.scheduler.minimum-allocation-mb为1024吗, container的自小申请为1024M的倍数,***注意:向上取整是yarn.scheduler.minimum-allocation-mb参数的倍数*,**为因此每个executor申请的内存为:

(1024+384)按照1g取整为2g,3个executor的内存为6G。

spark.yarn.am.memory为默认值512M+spark.yarn.executor.memoryOverhead为384M按照1G取整为1g,与提交命令中的driver-memory参数无关

ceil((1024+384)/1024)*3 +ceil((512+384)/1024)=7G

3. spark on yarn内存申请

3.1 yarn两个默认内存参数

yarn.scheduler.minimum-allocation-mb 每个container的最小内存值
yarn.scheduler.maximum-allocation-mb 每个container的最大内存值
也就是说,
a、如果你设置的spark.executor.memory参数值比yarn.scheduler.minimum-allocation-mb小,那yarn生成的container内存大小会默认会使用yarn.scheduler.minimum-allocation-mb的值。
b、如果你设置的spark.executor.memory参数值比yarn.scheduler.maximum-allocation-mb大,那yarn生成的container内存大小默认会使用yarn.scheduler.maximum-allocation-mb的值。
c、还有个隐藏的条件,yarn生成的container内存大小必须是yarn.scheduler.minimum-allocation-mb值的整数倍

3.2 spark

spark on yarn有一个memoryOverhead的概念,是为了防止内存溢出额外设置的一个值,可以用spark.yarn.executor.memoryOverhead参数手动设置,如果没有设置,默认memoryOverhead的大小由以下公式计算:
memoryOverhead = max(spark.executor.memory * 0.07,384)

// Executor memory in MB.
  protected val executorMemory = args.executorMemory
  // Additional memory overhead.
  protected val memoryOverhead: Int = sparkConf.getInt("spark.yarn.executor.memoryOverhead",
    math.max((MEMORY_OVERHEAD_FACTOR * executorMemory).toInt, MEMORY_OVERHEAD_MIN))
  // Number of cores per executor.
  protected val executorCores = args.executorCores
  // Resource capability requested for each executors
  private val resource = Resource.newInstance(executorMemory + memoryOverhead, executorCores)

3.3 yarn对spark任务内存的申请计算方式

现在我们看看上面的235520M = 230G是怎么计算出来的
前提:我们线上yarn的yarn.scheduler.minimum-allocation-mb设置的是2G
再把spark的参数列一下:
spark.executor.instances: 56
spark.executor.memory :2G
spark.driver.memory:5G

3.3.1 executer使用的内存计算

memoryOverhead = max(spark.executor.memory * 0.07,384)
= max(2 * 1024 * 0.07,384) = 384M
则一个executor实际要使用的内存大小为:
totalMemory = spark.executor.memory + memoryOverhead
= 2 * 1024 + 384 = 2432M
又因为yarn.scheduler.minimum-allocation-mb = 2G = 2048M
又由yarn的container内存大小的性质可知,container内存大小必须是yarn.scheduler.minimum-allocation-mb的整数倍,我们现在需要的内存大小是 2432M,而yarn.scheduler.minimum-allocation-mb是2048M,那么比2432M大且是2048M整数倍的最小值是4096M=4G,所以实际上yarn为spark申请的每个container的内存大小并不是我们设置的2G,而是4G
这样,我们有56个executor,也就是会申请56个container,则消耗的总内存是 56 * 4G = 224G

3.3.2 driver的内存计算

计算方式和上面一样:
memoryOverhead = max(spark.driver.memory * 0.07,384)
= max(5 * 1024 * 0.07,384) = 384M
则driver实际要使用的内存大小为:
totalMemory = spark.driver.memory + memoryOverhead
= 5 * 1024 + 384 = 5504M
同理,比5504M大且是2048M的整数倍的最小值是6144M=6G
故driver实际申请的内存大小是6G

所以整个spark任务最终申请的总内存大小为 224G + 6G = 230G