资源调度器是 YARN 中最外围的组件之一,它是 ResourceManager 中的一个插拔式服务组件,负责整个集群资源的治理和调配。
Yarn 默认提供了三种可用资源调度器,别离是 FIFO (First In First Out)、Yahoo! 的 Capacity Scheduler 和 Facebook 的 Fair Scheduler。
本节会重点介绍资源调度器的根本框架,在之后文章中具体介绍 Capacity Scheduler 和 Fair Scheduler。
一、根本架构
资源调度器是最外围的组件之一,并且在 Yarn 中是可插拔的,Yarn 中定义了一套接口标准,以不便用户实现本人的调度器,同时 Yarn 中自带了 FIFO,CapacitySheduler,FairScheduler 三种罕用资源调度器。
一)资源调度模型
Yarn 采纳了双层资源调度模型。
- 第一层中,RM 中的资源调度器将资源分配给各个 AM(Scheduler 解决的局部)
- 第二层中,AM 再进一步将资源分配给它的外部工作(不是本节关注的内容)
Yarn 的资源分配过程是 异步 的,资源调度器将资源分配给一个应用程序后,它不会立即 push 给对应的 AM,而是临时放到一个缓冲区中,期待 AM 通过周期性的心跳被动来取(pull-based 通信模型)
- NM 通过周期心跳汇报节点信息
- RM 为 NM 返回一个心跳应答,包含须要开释的 container 列表等信息
- RM 收到的 NM 信息触发一个 NODE_UPDATED 事件,之后会依照肯定策略将该节点上的资源分配到各个利用,并将调配后果放到一个内存数据结构中
- AM 向 RM 发送心跳,取得最新调配的 container 资源
- AM 将收到的新 container 调配给外部工作
二)资源示意模型
NM 启动时会向 RM 注册,注册信息中蕴含该节点可调配的 CPU 和内存总量,这两个值均可通过配置选项设置,具体如下:
yarn.nodemanager.resource.memory-mb
:可调配的物理内存总量,默认是 8Gyarn.nodemanager.vmem-pmem-ratio
:工作应用单位物理内存量对应最多可应用的虚拟内存,默认值是 2.1,示意应用 1M 的物理内存,最多能够应用 2.1MB 的虚拟内存总量yarn.nodemanager.resource.cpu-vcores
:可调配的虚构 CPU 个数,默认是 8。为了更细粒度地划分 CPU 资源和思考到 CPU 性能差别,YARN 容许管理员依据理论须要和 CPU 性能将每个物理 CPU 划分成若干个虚构 CPU,而管理员可为每个节点独自配置可用的虚构 CPU 个数,且用户提交应用程序时,也可指定每个工作须要的虚构 CPU 数
Yarn 反对的调度语义:
- 申请某个节点上的特定资源量
- 申请某个特定机架上的特定资源量
- 将某些节点退出(或移除)黑名单,不再为本人调配这些节点上的资源
- 申请偿还某些资源
Yarn 不反对的调度语义(随着 Yarn 的一直迭代,可能会在将来实现):
- 申请任意节点上的特定资源量
- 申请任意机架上的特定资源量
- 申请一组或几组合乎某种特质的资源
- 超细粒度资源。比方 CPU 性能要求、绑定 CPU 等
- 动静调整 Container 资源,容许依据须要动静调整 Container 资源量
三)资源保障机制
当单个节点的闲置资源无奈满足利用的一个 container 时,有两种策略:
- 放弃以后节点期待下一个节点;
- 在以后节点上预留一个 container 申请,等到节点有资源时优先满足预留。
YARN 采纳了第二种增量资源分配机制(当应用程序申请的资源临时无奈保障时,为应用程序预留一个节点上的资源直到累计开释的闲暇资源满足应用程序需要),这种机制会造成节约,但不会呈现饿死景象
四)层级队列治理
Yarn 的队列是层级关系,每个队列能够蕴含子队列,用户只能将工作提交到叶子队列。管理员能够配置每个叶子队列对应的操作系统用户和用户组,也能够配置每个队列的管理员。管理员能够杀死队列中的任何应用程序,扭转任何利用的优先级等。
队列的命名用 .
来连贯,比方 root.A1
、root.A1.B1
。
二、三种调度器
Yarn 的资源调度器是能够配置的,默认实现有三种 FIFO
、CapacityScheduler
、FairScheduler
。
一)FIFO
FIFO 是 Hadoop 设计之初提供的一个最简略的调度机制:先来先服务。
所有工作被对立提交到一个队里中,Hadoop 依照提交程序顺次运行这些作业。只有等先来的应用程序资源满足后,再开始为下一个应用程序进行调度运行和分配资源。
长处:
- 原理是和实现简略。也不须要任何独自的配置
毛病:
- 无奈提供 QoS,只能对所有的工作依照同一优先级解决。
- 无奈适应多租户资源管理。先来的大应用程序把集群资源占满,导致其余用户的程序无奈失去及时执行。
- 应用程序并发运行水平低。
二)Capacity Scheduler
Capacity Scheduler 容量调度是 Yahoo! 开发的多用户调度器,以队列为单位划分资源。
每个队列可设定肯定比例的资源最低保障和应用下限。每个用户也可设置肯定的资源应用下限,以防资源滥用。并反对资源共享,将队列残余资源共享给其余队列应用。配置文件名称为 capacity-scheduler.xml。
次要特点:
- 容量保障:可为每个队列设置资源最低保障(capacity)和资源应用下限(maximum-capacity,默认 100%),而所有提交到该队列的应用程序能够共享这个队列中的资源。
- 弹性调度:如果队列中的资源有残余或者闲暇,能够临时共享给那些须要资源的队列,一旦该队列有新的应用程序须要资源运行,则其余队列开释的资源会归还给该队列,从而实现弹性灵便调配调度资源,进步系统资源利用率。
- 多租户治理:反对多用户共享集群资源和多应用程序同时运行。且可对每个用户可应用资源量(user-limit-factor)设置下限。
- 平安隔离:每个队列设置严格的 ACL 列表(acl_submit_applications),用以限度能够用户或者用户组能够在该队列提交应用程序。
三)Fair Scheduler
Fair Scheduler 是 Facebook 开发的多用户调度器。设计指标是为所有的利用调配「偏心」的资源(对偏心的定义能够通过参数来设置)。偏心不仅能够在队列中的利用体现,也能够在多个队列之间工作。
在 Fair 调度器中,咱们不须要事后占用肯定的系统资源,Fair 调度器会为所有运行的 job 动静的调整系统资源。如下图所示,当第一个大 job 提交时,只有这一个 job 在运行,此时它取得了所有集群资源;当第二个小工作提交后,Fair 调度器会调配一半资源给这个小工作,让这两个工作偏心的共享集群资源。
与 Capacity Scheduler 不同之处:
四)源码继承关系
看上面三个图中调度器的继承关系。这三个 Scheduler 都继承自 AbstractYarnScheduler
。这个抽象类又 extends AbstractService implements ResourceScheduler。继承 AbstractService
阐明是一个服务,实现 ResourceScheduler
是 scheduler 的次要性能。
三者还有一些区别,FairScheduler
没实现 Configurable
接口,少了 setConf()
办法;FifoScheduler
不反对资源抢占,FairScheduler
反对资源抢占却没实现 PreemptableResourceScheduler
接口。
在 YarnScheduler
中,定义了一个资源调度器应该实现的办法。在 AbstractYarnScheduler
中实现了大部分办法,若本人实现调度器可继承该类,将发开重点放在资源分配实现上。
public interface YarnScheduler extends EventHandler<SchedulerEvent> {
// 取得一个队列的根本信息
public QueueInfo getQueueInfo(String queueName, boolean includeChildQueues,
boolean recursive) throws IOException;
// 获取集群资源
public Resource getClusterResource();
/**
* AM 和资源调度器之间最次要的一个办法
* AM 通过该办法更新资源申请、待开释资源列表、黑名单列表增减
*/
@Public
@Stable
Allocation allocate(ApplicationAttemptId appAttemptId,
List<ResourceRequest> ask, List<ContainerId> release,
List<String> blacklistAdditions, List<String> blacklistRemovals,
List<UpdateContainerRequest> increaseRequests,
List<UpdateContainerRequest> decreaseRequests);
// 获取节点资源应用状况报告
public SchedulerNodeReport getNodeReport(NodeId nodeId);
ResourceScheduler
实质是个事件处理器,次要解决 10 种事件(CapacityScheduler 还会多解决几种抢占相干的事件),能够到对应 Scheduler 的 handle()
办法中查看这些事件处理逻辑:
NODE_ADDED
: 集群中减少一个节点NODE_REMOVED
: 集群中移除一个节点NODE_RESOURCE_UPDATE
: 集群中有一个节点的资源减少了NODE_LABELS_UPDATE
: 更新 node labelsNODE_UPDATE
: 该事件是 NM 通过心跳和 RM 通信时发送的,会汇报该 node 的资源应用状况,同时触发一次调配操作。APP_ADDED
: 减少一个 ApplicationAPP_REMOVED
: 移除一个 applicationAPP_ATTEMPT_ADDED
: 减少一个 application AttemptAPP_ATTEMPT_REMOVED
: 移除一个 application attemptCONTAINER_EXPIRED
: 回收一个超时的 container
三、资源调度维度
目前有两种:DefaultResourceCalculator
和 DominantResourceCalculator
。
DefaultResourceCalculator
: 仅思考内存资源-
DominantResourceCalculator
: 同时思考内存和 CPU 资源(后续更新中反对更多类型资源,FPGA、GPU 等)。该算法扩大了最大最小偏心算法(max-min fairness)。- 在 DRF 算法中,将所需份额(资源比例)最大的资源称为主资源,而 DRF 的根本设计思维则是将最大最小偏心算法利用于主资源上,进而将多维资源调度问题转化为单资源调度问题,即 DRF 总是最大化所有主资源中最小的
- 感兴趣的话,可到源码中
DominantResourceCalculator#compare
探索实现逻辑 - 对应的论文《Dominant Resource Fairness: Fair Allocation of Multiple Resource Types》
(这里留神!很多文章和书中写的是「YARN 资源调度器默认采纳了 DominantResourceCalculator」,理论并不是这样的!)
FifoScheduler
默认应用DefaultResourceCalculator
且不可更改。CapacityScheduler
是在capacity-scheduler.xml
中配置yarn.scheduler.capacity.resource-calculator
参数决定的。FairScheduler
才默认应用DominantResourceCalculator
。
四、资源抢占模型
这里仅简要介绍资源抢占模型,在前面的文章中会深刻源码剖析抢占的流程。
- 在资源调度器中,每个队列可设置一个最小资源量和最大资源量,其中,最小资源量是资源紧缺状况下每个队列需保障的资源量,而最大资源量则是极其状况下队列也不能超过的资源使用量
- 为了进步资源利用率,资源调度器(包含 Capacity Scheduler 和 Fair Scheduler)会将负载较轻的队列的资源临时调配给负载重的队列,仅当负载较轻队列忽然收到新提交的应用程序时,调度器才进一步将本属于该队列的资源分配给它。
五、总结
本文介绍了 Yarn 资源调度器的根本框架,包含根本架构,以及简要介绍三种 YARN 实现的调度器,并对资源调度维度,资源抢占模型等进行了介绍。
后续文章中将会围绕三种 YARN 调度器,深刻源码进行探索。看其在源码中是如何一步步实现对应性能的。
参考文章:
《Hadoop 技术底细:深刻解析 YARN 架构设计与实现原理》第六章
深刻解析 yarn 架构设计与技术实现 - 资源调度器
Yarn 源码剖析 5 - 资源调度