Hadoop(12) Yarn和job提交源码解析
文章目录
Yarn基本架构
YARN(Yet Another Resource Negotiator) 主要由ResourceManager、NodeManager、ApplicationMaster和Container等组件构成,
架构图
组件介绍
ResourceManager
ResourceManager相当于Yarn集群的主节点, 其主要功能如下:
-
监控NodeManager
ResourceManager作为Yarn集群的主节点(相当于HDFS的NameNode), 负责监控其他节点上的NodeManager的状态, 比如是否存活, 各个Node上拥有的资源等, ResourceManager包括2个部分: ApplicationManager 和Scheduler:
- ApplicationManager负责管理监控各个系统的应用, 包括启动Applicaiton Master, 监控Applicaiton Master运行状态, 以及跟踪分配给Application Master的进度和状态
- Scheduler主要负责分配Container给Applicaiton Master, 分配算法有多种(如公平调度等等)可以根据需求不同选择适合的调度策略
-
处理客户端请求
当客户端发来一个job请求时, 就是由ResourceManager负责接收请求
-
Hadoop集群的资源的分配与调度(注意这里的资源不是只数据, 而是指CPU, 内存等)
当client提交job之后, ResourceManager根据任务计算该任务所需的资源, 然后分配MapTask数量和位置, 在MapTask介绍之后, 接着分配ReduceTask
-
启动和监控ApplicationMaster
当job提交之后, ResourceManager会在某个节点上启动一个ApplicationMaster, 然后由ApplicationMaster负责管理和监控这个job的执行, 并向ResourceManager报告任务的执行情况
NodeManager
NodeManager可以认为成Yarn集群的从节点(相当于HDFS的DataNode), 在每个从节点上都有一个NodeManager, 负责这个节点的资源管理, 其主要作用:
-
管理某个节点上的资源
NodeManager负责管理所在节点上的资源, 包括空闲资源和正在使用的资源, 并向ResourceManager报告, 当有任务请求资源时, NodeManager负责把部分资源封装成一个Container, 供给Task使用
-
处理来自ResourceManager的命令, 并向ResourceManager发送心跳
-
处理来自ApplicationManager的命令
当job提交之后, NodeManager会接受ApplicationManager的资源请求命令, 从而在本地启动相应的任务并执行
ApplicationManager
-
负责数据的切分
当一个job提交之后, ResourceManager在某个节点上启动一个ApplicationManager, 然后由这个ApplicationManager负责将处理的数据划分成不同的部分(对应MapReduce的切片)给不同的节点处理数据
-
为应用程序申请资源并分配任务
当Application启动之后, 会根据job分配不同的任务给其他的NodeManager, 然后由NodeManager执行任务
-
任务的监控与容错
任务分配完毕之后, ApplicationManager会实时监控各个NodeManager的执行情况, 如果出现错误, 会进行相应的处理(容错)
Container
一个概念, 本质上就是NodeManager接到资源请求之后, 封装的部分资源(几个处理器, 多少内存, 带宽等), 然后使用这个资源去执行相应的任务
Yarn工作机制
Yarn流程图
Yarn流程详解
- 首先Client(客户端)提交一个job请求到ResourceManager,其实就是申请一个ApplicationMaster
- ResourceManager收到请求之后, 返回给Client一个全局唯一的job_id和运行job所需资源的临时配置文件和提交路径(一般是在Hadoop根目录下的
tmp/
目录) - Client收到ResourceManager响应之后, 将这些配置文件和job的jar包提交到指定HDFS路径
- 提交完成之后, Client向ResourceManager再次发送请求申请开始运行ApplicationMaster
- ResourceManager初始化一个Task, 并将这个Task放入一个资源调度队列中
- 如果轮到这个Task执行, ResourceManager就会找一个NodeManager领取这个Task
- 在这个NodeManager上面申请一个Container, 并且在这个Contain中执行一个ApplicationMaster
- ApplicationMaster 会从刚刚Client提交的路径中下载临时的配置文件, 然后根据这些配置文件向ResourceManager申请创建相应数量的MapTask,前面说过, 一个切片(split)对应一个MapTask, 这些MapTask同样会放入资源调度队列中等待执行
- 等到队列中轮到这些MapTask, 就会向合适的NodeManager申请资源(Container)
- 资源充足的NodeManager会向ResourceManager申请领取MapTask任务, 领取成功就会在本地创建一个Container
- container 创建成功之后, ApplicationMaster会向NodeManager发送job的jar包和MapTask执行脚本, 然后MapTask就会在相应的节点上执行, 同时ApplicationMaster会监听NodeManager的执行情况, 直到所有的MapTask执行完毕, 执行完毕之后, NodeManager就会释放资源, 即释放Container
- ApplicationMaster接着向ResouceManager申请指定数量的Container 运行ReduceTask (ReduceTask数量由分区数量决定), 同MapTask 一样,会有相应数量的NodeManager在本地启动Container
- 各个ReduceTask 从刚刚执行MapTask 的节点上下载对应分区的数据, 然后开始执行ReduceTask, 执行完成之后释放资源
- ApplicationMaster 监听到所有的ReduceTask执行完毕, 然后向ResourceManager 发送请求, 注销自己
job提交的部分源码
源码细节
- 在Job提交之前,会先进行状态认证,只有
JobState
为DEFINE
状态时,才允许提交
/* waitForCompletion()方法 */
if (this.state == Job