本文基于Spark2.1.0版本
我们知道,使用yarn作为cluster manager时,spark(以client模式为例)用spark-submit提交应用程序(或者是spark-shell交互操作)不加任何资源参数时,会使用如下几个默认配置来向yarn的resourcemanager申请container资源:
spark.executor.memory 1g
spark.executor.cores 1
spark.executor.instances 2
spark.yarn.am.memory 512m
spark.yarn.am.cores 1
按照参数的默认值,yarn将会生成3个containers,第一个是container0,用来执行applicationmaster功能,另外两个container,就是分配给spark程序的CoarseGrainedExecutorBackend.
结合上面这些默认值,我们认为将会占用集群的3个vcores,3.5G memory。
看下图(yarn web ui),第一个问题来了,为什么memory使用的数量不是想象中的3.5g呢?
原来,yarn对于应用程序所要申请的内存资源,有两个参数来影响实际申请到内存容量:
第一个是yarn.scheduler.minimum-allocation-mb:最小可申请内存量,默认是1024。
第二个是规整化因子(FIFO和Capacity Scheduler时,规整化因子等于最小可申请资源量,不可单独配置;Fair Scheduler时,规整化因子通过参数yarn.scheduler.increment-allocation-mb设置,默认是1024),其作用是应用程序申请的资源如果不是该因子的整数倍,则将被修改为最小的整数倍对应的值。
由于每个容器都会占用一些额外的内存,所以导致CoarseGrainedExecutorBackend的每个容器实际使用的内存数 > 申请的1G,在规整化因子的作用下,这些容器实际申请的内存,就会是2G;而applicationmaster所在的容器,因为申请内存不到1G,则在最小可申请内存的作用下,实际申请的内存就会是1G。
这下申请的内存数就和图中的对上号了吧(5G)!
ok,继续往下说。
如果使用默认的2个executor,且每个executor只有1个vcore,毕竟执行任务的并发性太差。我们可以给每个executor多分配几个vcore来提高并发性。在提交应用程序时,增加 --executor-cores 4 配置。
那么,问题来了,为什么vcore的显示的不是我们配置的9呢(4+4+1)?依然是3,难道没有生效吗?
其实使用spark的driver ui观察,这里面的显示是准确的,说明我们想给每个executor使用4个core是生效了的。
可为什么yarn的web ui显示的不准确呢?
通过查资料发现,因为我们的capacity schedule使用的是DefaultResourceCalculator,那么DefaultResourceCalculator它在加载Container时其实仅仅只会考虑内存而不考虑cores。将capacity-scheduler.xml中的:
yarn.scheduler.capacity.resource-calculator
org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator
修改为:
yarn.scheduler.capacity.resource-calculator
org.apache.hadoop.yarn.util.resource.DominantResourceCalculator
(请注意每个节点的配置文件都需要修改,并且重启hadoop)
这时再提交spark应用程序,发现申请的vcores 的数目就对了吧(4+4+1)。
欢迎指正,转载请标明作者和出处,谢谢。