上一篇中我们在讲解 MapReduce 的时候,提到在 MapReduce1.0 中,MapReduce 既承担了分布式计算的任务,又兼备资源管理和作业控制两大功能。这好比一个皇帝不放权,无论什么事情都是亲力亲为,那么皇帝也是精力有限的,即使工作007,也不能兼顾到每件事都做好,万一哪天进了 ICU,那所有的事都会被搁置。在 MapReduce1.0 中,JobTracker
就是这样一个不放权的皇帝,既要管分布式计算,又要管资源调度(只支持 MapReduce 编程模型),还要管作业控制。这就导致了当集群中的 MR 任务很多时,造成 JobTracker
很大的内存开销,而且一旦 JobTracker
挂了,那么整个 MapReduce 集群的所有 MR 任务都会失败。另外,JobTracker
对资源的划分并不合理,JobTracker
只是简单地将内存、cpu等资源打包切分成 slots
,然后在任务执行之前就规定好了 map slots
和 reduce slots
,在任务执行过程中,map slots
和 reduce slots
资源不可以互相侵占,导致资源的浪费。鉴于 MapReduce1.0 暴露出来的种种问题,官方研发团队痛定思痛,决定将存在于 MapReduce1.0 中的资源管理和作业调度抽取出来,加以改进形成 Yet Another Resource Negotiator,意为 另一种资源调度器,也就是我们本篇的主角 Yarn!
Yarn 的设计思路
在前面的系列文章中,我们已经零散地提到了一些 Yarn 的设计和优化,在本篇,我们再总结一下:
- MapReduce1.0 既是一个计算框架,也是一个资源管理和作业调度框架。
- Yarn 是将 MapReduce1.0 中的资源管理和作业调度功能剥离出来并加以优化产生的,是一个纯粹的资源管理调度框架,而不是一个计算框架。
- 被剥离了资源管理调度功能的 MapReduce1.0 变成了 MapReduce2.0,它是一个运行在 Yarn 之上的计算框架,不再具备资源管理和作业调度功能。
Yarn 的体系结构
下面我们会围绕着上图展开介绍图中的各个组件:
ResourceManager
ResourceManager 是整个 Yarn 架构的 Master 节点,负责处理客户端的请求,启动和监控 ApplicationMaster,监控 NodeManager,负责资源管理分配与调度。ResourceManager(RM)是一个全局的资源管理器,负责整个系统的资源管理和分配,主要包括两个组件,即调度器(Scheduler)和应用程序管理器(Applications Manager)。
Scheduler 调度器接受来自 ApplicationMaster 的应用程序资源请求,把集群中的资源以容器(container)的形式分配给提出申请的应用程序,container 的选择通常会考虑应用程序所要处理的数据的位置,进行就近选择,从而实现 “移动计算”。
Container 容器作为 Yarn 的动态资源分配单位,是 Yarn 对资源做的一层抽象,Yarn 将cpu、内存和磁盘这些计算资源都封装成一个个 Container,从而限定了每个应用程序可以使用的资源量,有效地实现了应用程序的资源隔离。
Applications Master 应用程序管理器负责系统中所有应用程序的管理工作,主要包括应用程序提交、与 Scheduler 协商资源以启动 ApplicationMaster、监控 ApplicationMaster 运行状态并在失败时重新启动任务等。
ApplicationMaster
ResourceManager 接受到用户提交的作业,按照作业的上下文信息以及从 NodeManager 收集上来的容器的状态信息,启动调度过程,为用户的作业启动一个 ApplicationMaster,ApplicationMaster 也是运行在容器中。
ApplicationMaster 主要工作:
- 当用户提交作业时,ApplicationMaster 与 ResourceManager 协商获取资源,ResourceManager 会以容器的形式为 ApplicationMaster 分配资源。
- ApplicationMaster 一旦申请到资源,会把获得的资源进一步分配给内部的各个任务(Map 任务或者 Reduce 任务),从而实现资源的二次分配。
- 与 NodeManager 保持交互通信,进行应用程序的启动、运行、监控和停止,监控申请到的资源的使用情况,对所有任务的执行进度和状态进行监控,并在任务发生失败时执行失败恢复,即重新申请资源重启任务。
- 定时向 ResourceManager 发送“心跳”消息,报告资源的使用情况和应用执行的进度信息。
- 当作业完成时,ApplicationMaster 向 ResourceManager 注销容器。
NodeManager
NodeManager 就是驻守在每个节点上的资源管理代理,处理来自 ResourceManager 的命令,也要处理来自 ApplicationMaster 的命令。
NodeManager 的主要工作:
- 管理容器的生命周期,监控每个容器的资源的使用情况。
- 以“心跳”的方式与 ResourceManager 保持通信,并向 ResourceManager 汇报作业的资源使用情况和每个容器的运行状态。
- 监控节点的健康状况。
- 接收来自 ApplicationMaster 的启动和停止容器的请求。
注意,NodeManager 主要负责管理容器,只处理与容器相关的事情,不会具体负责到每个任务(Map 任务或者 Reduce 任务)自身状态的管理。因为这些任务的管理时由 ApplicationMaster 完成的,ApplicationMaster 会通过不断与 NodeManager 通信来掌握各个任务的执行状态。
Yarn 的工作流程
- 用户将编写的应用程序通过 Client 向 Yarn 提交。
- Yarn 中的 ResourceManager 负责接收和处理来自 Client 的请求,为应用程序分配一个容器,在该容器中启动一个 ApplicationMaster。
- ApplicationMaster 被创建后会首先向 ResourceManager 注册。
- ApplicationMaster 采用轮询的方式向 ResourceManager 申请资源,每一个 Map 任务、Reduce 任务都需要一个单独的 Container 去执行。
- ResourceManager 以 Container 的形式向提出申请的 ApplicationMaster 分配资源。
- ApplicationMaster 申请到 Container 之后,会对 Container 进行 “二次分配”,分配给 ApplicationMaster 管理的各个 Map 任务和 Reduce 任务,每个 Container 中都有一份运行时环境、程序脚本和 jar 包等。
- 各个任务向 ApplicationMaster 汇报自己的状态和进度,如果任务失败就要恢复。
- 应用程序运行完成后,ApplicationMaster 向 ResourceManager 的应用程序管理器注销。
Yarn 的多租户设定
Yarn 提供了三种可用资源调度器,分别是 FIFO Scheduler、Capacity Scheduler 和 Fair Scheduler。
FIFO Scheduler 即先来先服务。所有的应用程序被统一提交到一个队列中,按照提交顺序依次运行。优点是实现简单,不需要任何额外的配置。缺点是无法适应多租户资源管理。如果先来的大程序占满了集群资源,导致其他用户的程序无法得到及时执行,应用程序的并发程度很低。这种方案基本不会被采用。
Capacity Scheduler 容量调度即是以队列为单位进行划分资源。每个队列可以设定一定比例的最低资源和最高使用上限。每个用户也可以设置一定的资源使用上限,以防止资源的滥用。并支持资源共享,将队列剩余资源给其他队列使用,配置的文件为 capacity-scheduler.xml
。
Fair Scheduler 该调度器是由 Facebook 开发,设计目标是为所有的应用公平地分配资源。这里的公平可以举个例子来体会:“假设有两个用户 A 和 B,他们分别拥有一个队列,且分别设置容量最小为集群的一半,最大为全部集群资源。当 A 启动一个 job 而 B 没有任务时,A 会获得全部集群资源;当 B 启动一个 job 后,A 的 job 会继续运行,不过一会儿之后两个任务会各自获得一半的集群资源。如果此时B再启动第二个job并且其它job还在运行,则它将会和B的第一个 job 共享 B 这个队列的资源,也就是 B 的两个 job 会用于四分之一的集群资源,而 A 的 job 仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共享”。
上图是采用 Capacity Scheduler
调度方式,下图是采用 Fair Scheduler
调度方式:
Yarn 的愿景
Yarn 的目标是在一个Yarn 框架之上支持多种计算框架。对于一个企业来说,同时存在不同的业务场景,比如需要离线批处理 MapReduce 框架,需要 Impala 实现实时交互式查询分析,需要 Flink 实现流式数据实时分析,需要 Spark 实现迭代计算等等,这些计算框架都会自带资源管理功能,如果用其自带的资源管理框架去管理任务就会产生一个问题:“不同的资源管理框架在一个集群中不兼容”。企业为了避免上述问题就会把一个大集群切分成很多的独立的小集群,但这又会带来一个问题:“每个小集群的数据不共享,资源利用率很低且维护代价高”。Yarn 的出现将上述矛盾都解开了,实现了“一个集群多个框架”,即在一个集群上部署一个统一的资源调度框架 Yarn,在 Yarn 之上可以部署其他的各种计算框架。Yarn 为这些激素三框架提供统一的资源调度管理服务,并且能够根据各种计算框架的负载需求,调整各自占用的资源,实现集群资源共享和资源的弹性收缩。不同的计算框架共享底层存储,避免了数据集跨集群移动。实现了一个集群上的不同应用负载混搭,有效提高了集群的资源利用率。
自此,Yarn 破了 MapReduce1.0 的茧,化成了蝶!