上一篇讲到Yarn是什么?讲到这,我们知道其有哪些调度方式吗?
YARN之三种调度方式:
下面主要讲CapacityScheduler实现逻辑:
一、应用程序初始化
应用程序被提交到ResourceManager之后,ResourceManager会向Capacity Scheduler发送一个SchedulerEventType.APP_ADDED事件,Capacity Scheduler收到该事件后,将为应用程序创建一个FiCaSchedulerApp对象跟踪和维护该应用程序的运行时信息,同时将应用程序提交到对应的叶子队列中,叶子队列会对应用程序进行一系列检查,包括以下几个方面:
1. 应用程序所属用户拥有该叶子队列的应用程序提交权限
2. 队列及其父队列当前处于RUNNING状态(递归检查)
3. 队列当前已提交的应用程序数目未达到管理员设定的上限
4. 应用程序所属用户提交的应用程序数目未超过管理员设定的上限
二、资源调度
当ResourceManager收到来自NodeManager发送的心跳信息后,将向Capacity Scheduler发送一个SchedulerEventType.NODE_UPDATE事件,Capacity Scheduler收到该事件后,会依次进行以下操作:
1. 处理心跳信息:NodeManager发送的心跳信息中有两类信息需资源调度器处理,一类是最新启动的Container,另一类是运行完成的Container,具体如下:
对于最新启动的Container,资源调度器需向ResourceManager发送一个RMContainerEventType.LAUNCHED,进而将该Container从超时监控队列中删除。当资源调度器为ApplicationMaster分配一个Container后,为了防止ApplicationMaster长时间不使用该Container造成资源浪费,它会将该Container加入一个超时监控队列中。如果一段时间内,该队列中的Container仍未被使用,则资源调度器会回收该Container。
对于运行完成的Container,资源管理器将回收它使用的资源,以便接下来对这些资源进行再分配。
处理完以上两类信息后,Capacity Scheduler将节点上的空闲资源分配给应用程序。
2. 资源分配:
(1). Container主要包含5类信息:
优先级(底层根本:FIFO原则、其他优先级配置)
期望资源所在节点(节点标签管理)
资源量(依据预留、个人、队列等容量设置)
Container数目是否松弛本地性(即是否在没有满足节点本地性资源时,选择机架本地性资源)延迟度
(2). 资源调度器收到资源申请后,会暂时将这些数据请求存放到一个数据结构中,以等待空闲资源出现后为其分配合适的资源。
(3). 当一个节点上有空闲资源时,它会依次选择队列、应用程序和container(请求)使用该资源:
Step1:选择队列
从根队列开始,使用深度优先遍历算法,从根队列开始,依次遍历子队列找出资源使用率最小的子队列。若子队列为叶子队列,则选择该队列,从而进行step2、step3;若子队列为非叶子队列,则以该子队列为根队列重复前面的过程直到找到一个资源使用率最小的叶子队列为止。
注意:上述“队列资源使用率”计算方法为已经使用的资源量除以最小队列资源容量(由管理员配置)。对于非叶子队列,它的已使 用资源量是各个子队列已使用资源量之和。
Step2:选择应用程序
在Step1中选好了叶子队列后,取该队列中最早提交的应用程序(实际排序时用的 Application ID,提交时间越早的应用程序,Application ID 越小)。
Step3:选择 Container
在 Step2中选好应用程序之后,对于同一个应用程序,它请求的Container可能是多样化的,涉及不同的优先级、节点、资源量和数量。当选中一个应用程序后,Capacity Scheduler将尝试优先满足优先级高的Container。对于同一类优先级,优先选择满足本地性的Container,它会依次选择node local、rack local和no local的Container。
(4). 在 Capacity Scheduler 中,在比较资源使用率时,不同的资源比较器对资源定义是不一样的。默认的是 DefaultResourceCalculator,它只考虑Memory资源。另外一种是 DominantResourceCalculator,采用了 DRF 比较算法,同时考虑Memory和 cpu 两种资源。通过参数 yarn.scheduler.capacity.resource-calculator 来设置。
(5). 其他事件处理
APP_REMOVED:在多种情况下Capacity Scheduler将收到该事件,包括应用程序正常结束、应用程序被杀死等。Capacity Scheduler收到该事件后,首先会向所有未运行完成的Container发送一个RMContainerEventType.KILL事件,以释放正在使用的Container;然后才会将应用程序相关数据结构从内存中移除。
NODE_ADDED:当集群中动态加入一个节点时(比如管理员动态扩充集群规模或者节点断开后又复活等),Capacity Scheduler将收到该事件。Capacity Scheduler收到该事件后,只需在相应数据结构中记录NodeManager信息并增加系统总资源量即可。
NODE_REMOVED:当集群中动态移除一个节点时(比如管理员动态移除节点或者节点在一定事件内未汇报心跳而被ResourceManager移除集群),Capacity Scheduler将收到该事件。Capacity Scheduler收到该事件后,除了移除NodeManager信息并减少系统总资源外,还需向所有正运行的Container发送一个RMContainerEventType.KILL事件,以清空相关信息。
CONTAINER_EXPIRED:当Capacity Scheduler将一个Container分配给ApplicationMaster后,ApplicationMaster在一定时间内必须使用该Container,否则ResourceManager将进行强制回收,此时会触发一个CONTAINER_EXPIRED事件。
CS资源分配流程:
Step1:选择队列
从根队列开始,使用深度优先遍历算法,从根队列开始,依次遍历子队列找出资源占用率最小的子队列。若子队列为叶子队列,则选择该队列;若子队列为非叶子队列,则以该子队列为根队列重复前面的过程直到找到一个资源使用率最小的叶子队列为止。
Step2:选择应用
在Step1中选好了叶子队列后,取该队列中最早提交的应用程序(实际排序时用的 Application ID,提交时间越早的应用程序,Application ID 越小)。
Step3:选择 Container
在 Step2中选好应用程序之后,选择该应用程序中优先级最高的 Container。对于优先级相同的 Containers,优选选择满足本地性的 Container,会依次选择 node local、rack local、off switch,在 Ca