一、Yarn通俗介绍
Apache Hadoop YARN (Yet Another Resource Negotiator,另一种资源协调者)是一
种新的 Hadoop 资源管理器,它是一个通用资源管理系统和调度平台,可为上层应用提供统
一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨
大好处。
可以把 yarn 理解为相当于一个分布式的操作系统平台,而 mapreduce 等运算程序则相
yarn 并不清楚用户提交的程序的运行机制
yarn 只提供运算资源的调度(用户程序向 yarn 申请资源,yarn 就负责分配资源)
yarn 中的主管角色叫 ResourceManager
yarn 中具体提供运算资源的角色叫 NodeManager
yarn与运行的用户程序完全解耦,意味着yarn上可以运行各种类型的分布式运算程序,
比如 mapreduce、storm,spark,tez ……
spark、storm 等运算框架都可以整合在 yarn 上运行,只要他们各自的框架中有符合
yarn 规范的资源请求机制即可
yarn 成为一个通用的资源调度平台.企业中以前存在的各种运算集群都可以整合在一
个物理集群上,提高资源利用率,方便数据共享
二、yarn基本架构
YARN 是一个资源管理、任务调度的框架,主要包含三大模块:ResourceManager(RM)、
NodeManager(NM)、ApplicationMaster(AM)。
ResourceManager 负责所有资源的监控、分配和管理;
ApplicationMaster 负责每一个具体应用程序的调度和协调;
NodeManager 负责每一个节点的维护。
对于所有的 applications,RM 拥有绝对的控制权和对资源的分配权。而每个 AM 则会和
RM 协商资源,同时和 NodeManager 通信来执行和监控 task。
三、Yarn三大组件介绍
1.ResourceManager
ResourceManager 负责整个集群的资源管理和分配,是一个全局的资源管理系统。
NodeManager 以心跳的方式向 ResourceManager 汇报资源使用情况(目前主要是 CPU 和
内存的使用情况)。RM 只接受 NM 的资源回报信息,对于具体的资源处理则交给 NM 自己
处理。
YARN Scheduler 根据 application 的请求为其分配资源,不负责 application job 的
监控、追踪、运行状态反馈、启动等工作。
2. NodeManager
NodeManager 是每个节点上的资源和任务管理器,它是管理这台机器的代理,负责该节
点程序的运行,以及该节点资源的管理和监控。YARN 集群每个节点都运行一个
NodeManager。
NodeManager 定时向 ResourceManager 汇报本节点资源(CPU、内存)的使用情况和
Container 的运行状态。当 ResourceManager 宕机时 NodeManager 自动连接 RM 备用节
点。
NodeManager 接收并处理来自 ApplicationMaster 的 Container 启动、停止等各种请
求。
3.ApplicationMaster
用 户 提 交 的 每 个 应 用 程 序 均 包 含 一 个 ApplicationMaster , 它 可 以 运 行 在
ResourceManager 以外的机器上。
负责与 RM 调度器协商以获取资源(用 Container 表示)。
将得到的任务进一步分配给内部的任务(资源的二次分配)。
与 NM 通信以启动/停止任务。
监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务。
当前 YARN 自带了两个 ApplicationMaster 实现,一个是用于演示 AM 编写方法的实例
程序 DistributedShell,它可以申请一定数目的 Container 以并行运行一个 Shell 命
令或者 Shell 脚本;另一个是运行 MapReduce 应用程序的 AM—MRAppMaster。
注:RM 只负责监控 AM,并在 AM 运行失败时候启动它。RM 不负责 AM 内部任务的容错,
任务的容错由 AM 完成。
四、Yarn运行流程
步骤1 用户向YARN中提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
步骤2 ResourceManager为该应用程序分配第一个Container,并与对应的Node-Manager通信,要求它在这个Container中启动应用程序的ApplicationMaster。
步骤3 ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManager查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7。
步骤4 ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源。
步骤5 一旦ApplicationMaster申请到资源后,便与对应的NodeManager通信,要求它启动任务。
步骤6 NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。
步骤7 各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。
在应用程序运行过程中,用户可随时通过RPC向ApplicationMaster查询应用程序的当前运行状态。
步骤8 应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。
五、Yarn调度器Scheduler
理想情况下,我们应用对 Yarn 资源的请求应该立刻得到满足,但现实情况资源往往是
有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到
相应的资源。在 n Yarn 中,负责给应用分配资源的就是 Scheduler。其实调度本身就是一个
难题,很难找到一个完美的策略可以解决所有的应用场景。为此,Yarn 提供了多种调度器
和可配置的策略供我们选择。
在 Yarn 中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,Fair
Scheduler。
三种调度器:
1.FIFO Scheduler
FIFO Scheduler 把应用按提交的顺序排成一个队列,这是一个 先进先出队列,在进行
资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给
下一个分配,以此类推。
FIFO Scheduler 是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适
用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞。在共享集群
中,更适合采用 Capacity Scheduler 或 Fair Scheduler,这两个调度器都允许大任务和小
任务在提交的同时获得一定的系统资源。
2.Capacity Scheduler
Capacity 调度器允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能
力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集
群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内部又可以垂直
划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的
调度是采用的是先进先出(FIFO)策略。
3.Fair Scheduler
在 Fair 调度器中,我们不需要预先占用一定的系统资源,Fair 调度器会为所有运行的
job 动态的调整系统资源。如下图所示,当第一个大 job 提交时,只有这一个 job 在运行,
此时它获得了所有集群资源;当第二个小任务提交后,Fair 调度器会分配一半资源给这个
小任务,让这两个任务公平的共享集群资源。
需要注意的是,在下图 Fair 调度器中,从第二个任务提交到获得资源会有一定的延
迟,因为它需要等待第一个任务释放占用的 Container。小任务执行完成之后也会释放自
己占用的资源,大任务又获得了全部的系统资源。最终效果就是 Fair 调度器即得到了高的
资源利用率又能保证小任务及时完成。
调度器的使用是通过 yarn-site.xml 配置文件中的
yarn.resourcemanager.scheduler.class 参数进行配置的, 默认采用 Capacity
Scheduler 调度器。
假设我们有如下层次的队列:
下面是一个简单的 Capacity 调度器的配置文件,文件名为 capacity-scheduler.xml。
在这个配置中,在 root 队列下面定义了两个子队列 prod 和 dev,分别占 40%和 60%的容量。
需要注意,一个队列的配置是通过属性 yarn.sheduler.capacity.<queue-path>.<sub-
property>指定的,<queue-path>代表的是队列的继承树,如 root.prod 队列,<sub-property>
一般指 capacity 和 maximum-capacity。
<configuration>
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>prod,dev</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.queues</name>
<value>mapreduce,spark</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.prod.capacity</name>
<value>40</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.capacity</name>
<value>60</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.maximum-capacity</name>
<value>75</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.mapreduce.capacity</name>
<value>50</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.spark.capacity</name>
<value>50</value>
</property>
</configuration>
dev 队列又被分成了 mapreduce 和 spark 两个相同容量的子队列。dev
的 maximum-capacity 属性被设置成了 75%,所以即使 prod 队列完全空闲 dev 也不会占用全
部集群资源,也就是说,prod 队列仍有 25%的可用资源用来应急。我们注意到,mapreduce
和 spark 两个队列没有设置 maximum-capacity 属性,也就是说 mapreduce 或 spark 队列中
的 job 可能会用到整个 dev 队列的所有资源(最多为集群的 75%)。而类似的,prod 由于没
有设置 maximum-capacity 属性,它有可能会占用集群全部资源。
关于队列的设置,这取决于我们具体的应用。比如,在 MapReduce 中,我们可以通过
mapreduce.job.queuename 属性指定要用的队列。如果队列不存在,我们在提交任务时就
会收到错误。如果我们没有定义任何队列,所有的应用将会放在一个 default 队列中。
注意:对于 Capacity 调度器,我们的队列名必须是队列树中的最后一部分,如果我们
使用队列树则不会被识别。比如,在上面配置中,我们使用 prod 和 mapreduce 作为队列名
是可以的,但是如果我们用 root.dev.mapreduce 或者 dev. mapreduce 是无效的。
版权声明:本文为qq_33624952原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。