1. Yarn架构
1.1 简介
1.1.1 架构
YARN主要由ResourceManager、NodeManager、ApplicationMaster和Container等几个组件构成。
YARN总体上仍然是Master/Slave结构,在整个资源管理框架中,ResourceManager为Master,NodeManager为Slave,ResourceManager负责对各个NodeManager上的资源进行统一管理和调度。当用户提交一个应用程序时,需要提供一个用以跟踪和管理这个程序的ApplicationMaster,它负责向ResourceManager申请资源,并要求NodeManger启动可以占用一定资源的任务。由于不同的ApplicationMaster被分布到不同的节点上,因此它们之间不会相互影响。
1.1.2 Job提交流程
- 用户向YARN中提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
- ResourceManager为该应用程序分配第一个Container,并与对应的Node-Manager通信,要求它在这个Container中启动应用程序的ApplicationMaster。
- ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManager查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7。
- ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源。
- 一旦ApplicationMaster申请到资源后,便与对应的NodeManager通信,要求它启动任务。
- NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。
- 各个任务通过RPC协议向ApplicationMaster汇报自己的状态和进度,以便让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可随时通过RPC向ApplicationMaster查询应用程序的当前运行状态。
- 应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。
1.2 组件介绍
1.2.1 ResourceManager(RM)
RM 是一个全局的资源管理器,负责整个系统的资源管理和分配。它主要由两个组件构成:调度器(Scheduler)和应用程序管理器(Applications Manager)。
调度器(Scheduler)
调度器根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。
需要注意的是,该调度器是一个“纯调度器”,它不再从事任何与具体应用程序相关的工作,比如不负责监控或者跟踪应用的执行状态等,也不负责重新启动因应用执行失败或者硬件故障而产生的失败任务,这些均交由应用程序相关的ApplicationMaster完成。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位用一个抽象概念“资源容器”(Resource Container,简称Container)表示,Container是一个动态资源分配单位,它将内存、CPU、磁盘、网络等资源封装在一起,从而限定每个任务使用的资源量。此外,该调度器是一个可插拔的组件,用户可根据自己的需要设计新的调度器。
在Yarn中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,Fair Scheduler。
FIFO Scheduler
FIFO Scheduler把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
Capacity Scheduler
Capacity 调度器允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
在正常的操作中,Capacity调度器不会强制释放Container,当一个队列资源不够用时,这个队列只能获得其它队列释放后的Container资源。当然,我们可以为队列设置一个最大资源使用量,以免这个队列过多的占用空闲资源,导致其它队列无法使用这些空闲资源,这就是”弹性队列”需要权衡的地方。
配置方法:
Capacity调度器的配置文件,文件名为capacity-scheduler.xml
# 例如以下队列 root ├── prod 40% └── dev 60% ~ 75% ├── eng 50% └── science 50%
上面队列配置如下:
<?xml version="1.0"?> <configuration> <!-- 定义了两个子队列prod和dev --> <property> <name>yarn.scheduler.capacity.root.queues</name> <value>prod, dev</value> </property> <!-- dev队列又被分成了eng和science --> <property> <name>yarn.scheduler.capacity.root.dev.queues</name> <value>eng, science</value> </property> <!-- 队列prod占40%的容量 --> <property> <name>yarn.scheduler.capacity.root.prod.capacity</name> <value>40</value> </property> <!-- 队列dev占60%的容量 --> <property> <name>yarn.scheduler.capacity.root.dev.capacity</name> <value>60</value> </property> <!-- 限制dev的最大资源伸缩比重为75%,所以即使prod队列完全空闲dev也不会占用全部集群资源 --> <property> <name>yarn.scheduler.capacity.root.dev.maximum-capacity</name> <value>75</value> </property> <!-- 队列eng占50%的容量,由于没有设置最大值,所以可能占用整个父队列的资源 --> <property> <name>yarn.scheduler.capacity.root.dev.eng.capacity</name> <value>50</value> </property> <!-- 队列science占50%的容量,由于没有设置最大值,所以可能占用整个父队列的资源 --> <property> <name>yarn.scheduler.capacity.root.dev.science.capacity</name> <value>50</value> </property> </configuration>
Capacity容器除了可以配置队列及其容量外,我们还可以配置一个用户或应用可以分配的最大资源数量、可以同时运行多少应用、队列的ACL认证等。
在MapReduce中,我