文章目录
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-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-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