一 MRAppMaster介绍
MRAppMaster是MapReduce的ApplicationMaster实现,它使得Map
Reduce可以直接运行在YARN上,它主要作用在于管理作业的生命周期:
1.1作业的管理:作业的创建,初始化以及启动等
1.2向RM申请资源和再分配资源
1.3Container的启动与释放
1.4监控作业运行状态
1.5作业恢复
二 所涉及到的类
Job:表示一个MapReduce作业,负责监控作业的运行状态,他维护了一个作业的状态机,以实现异步执行各种作业相关操作
Task:表示一个MapReduce作业的某个任务,负责监控一个任务的运行状态。它维护了一个任务状态机,以实现各种任务相关的操作
TaskAttempt:表示一个任务运行实例。一般正常情况一个Task就一个TaskAttempt,如果启用了推测执行,或者遇到了Task失败,那么可能有多个,但是只要有一个执行成功,就会kill掉其他的
TaskCleaner:负责清理失败任务或被杀死的任务所使用的 目录和产生的垃圾数据。
在YARN中,任务实例是运行在Container中的,因此Container的状态变化往往伴随TaskAttempt的状态变化。比如TaskAttempt运行完毕,会清理Container占用的空间,而Container空间的清理实际上就是任务实例空间的清理。任务实例运行完毕后,需要向MRAppMaster
请求提交结果,一旦提交完成,该任务的其他实例会被杀死。
当一个Container运行结束后,MRAppMaster可直接从ResourceManager上获知。各个任务运行实例需定期向MRAppMaster汇报进度和状态,否则MRAppMaster认为该任务处于僵死状态,会将它杀死,每次汇报均会触发一个TA_UPDATE事件。
当任务执行失败,MRAppMaster会向RM申请释放这个失败任务的Container,然后重新为这个任务分配资源。
Speculator:执行推测执行功能。当一个作业的某个任务速度明显慢于其他任务时,会为该任务启动一个备份任务,谁先完成,就把另一个结束掉
ContainerLuancher:负责与NM通信,已启动一个Container.当RM为作业分配资源后,ContainerLuancher会将任务执行相关信息填充到Container中,包括运行所需要的资源,任务运行命令,任务运行环境等,然后要求NM启动Container
TaskAttemptListener:负责管理各个任务的心跳信息,如果一个任务一段时间内未汇报心跳,则认为他挂了,会将其从系统中移除。
JobHistoryEventHandler:负责对作业的各个时间进行记录。当MRAppMaster出现故障的时候,YARN会将其重新调度到,另一个节点。
三 MRAppMaster工作流程
3.1用户向YARN中(RM)提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
3.2ResourceManager为该应用程序分配第一个Container,ResouceManag与某个NodeManager通信,启动应用程序ApplicationMaster,NodeManager接到命令后,首先从HDFS上下载文件(缓存),然后启动ApplicationMaser。
3.3 当ApplicationMaster启动后,它与ResouceManager通信,以请求和获取资源。ApplicationMaster获取到资源后,与对应NodeManager通信以启动任务。
注:
1.如果该应用程序第一次在给节点上启动任务,则NodeManager首先从HDFS上下载文件缓存到本地,这个是由分布式缓存实现的,然后启动该任务。
2.分布式缓存并不是将文件缓存到集群中各个结点的内存中,而是将文件换到各个结点的磁盘上,以便执行任务时候直接从本地磁盘上读取文件。
4ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManage查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它们的运行状态,直到运行结束,即重复步骤5~8
5ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源
6一旦ApplicationMaster申请到资源后,ApplicationMaster就会将启动命令交给NodeManager,要求它启动任务。启动命令里包含了一些信息使得Container可以与ApplicationMaster进行通信。
7NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务(Container)。
8在应用程序运行过程中,用户可随时通过RPC向ApplicationMaster查询应用程序的当前运行状态
9应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己
二 首先,MRAppMaster继承了CompositeService,即MRAppMaster是一种服务,那我们首先看启动方法serviceStart():
#调用createJob方法创建Job
#创建Job初始化事件JobEvent
#调用JobEventDispatcher#handle,处理job初始化事件
#设置Job的类加载器
#作业初始化失败,构造JOB_INIT_FAILED事件,并交由事件分发器JobEventDispatcher处理;如果成功调用startJobs方法启动作业
三 其次我们知道MRAppMaster启动就会创建并初始化job,那么是如何初始化的呢?
最终是通过JobImpl静态内部类InitTransition的transition()方法来实现。
#调用setupJob完成作业启动前的部分初始化工作
#创建作业已提交事件
#调用createSplits创建分片, 并获取任务分片元数据信息
#确定MapTask数目:分片元数据信息数组长度,即有多少分片就有多少MapTask数量
#确定ReduceTask数目:取决于作业参数mapreduce.job.reduces
#根据分片元数据信息计算inputLength输入长度,也就是作业大小
#根据作业大小,决定运行作业的方式Uber或者NON-Uber模式
#创建MapTask和 ReduceTask
四 再次,作业初始化之后,我们就需要开启job呢,具体实现如下:
#构造JOB-START事件,然后将该事件交由分发器处理
#调用JobImpl的静态内部类StartTransition#transition来处理
设置作业起始时间
构造提交作业的Setup事件CommiterJobSetupEvent,并交给事件分发器处理
最后调度作业MapTask和 ReduceTask,如果没有Task了,则声称JOB_INIT事件。
五 资源申请和再分配
ContainerAllocator是MRAppMaster中负责资源申请和分配的模块。用户提交的作业被分解成MapTask和ReduceTask后,这些Task所需的资源统一由ContainerAllocator模块负责从ResourceManager中申请,而一旦ContainAllocator得到资源后,需采用一定的策略进一步分配给作业的各个任务。
六 资源申请和再分配
一旦MRAppMaster收到新分配的Container后,会将这Container进一步分配给各个任务,Container分配过程如下:
1.判断新收到的Container包含的资源是否满足,如果不满足,则通过下次心跳通知ResourceManager释放该Container.
2.判断收到的Container所在的节点是否被加入到黑名单中,如果是,则寻找一个与该Container匹配的任务,并重新为该任务申请资源,同时通过下次心跳通知ResourceManager释放该Container.
3.根据Container的优先级,将它分配给对应类型的任务。
七 Container启动与释放
当ContainerAllocator为某个任务申请到资源后,会将运行该任务相关的所有信息封装到Container中,并要求对应的节点启动该Container。需要注意的是,Container中运行的任务对应的数据处理引擎与MRv1中完全一致,仍为MapTask和 ReduceTask。正因为如此,MRv1的程序与YARN中的MapReduce程序完全兼容。
ContainerLaunche负责与各个NodeManager通信,已启动或者释放Container。在YARN中,运行的Task所需的全部信息被封装到Container中,包括所需的资源、依赖的外部文件、JAR包、运行时环境变量、运行命令等。ContainerLauncher通过RPC协议ContainerManager与NodeManager通信,以控制Container的启动和释放,进而控制任务的执行(比如启动任务、杀死任务等)。
有多种可能触发停止/杀死一个Container,常见的有:
1.推测执行时一个任务运行完成,需杀死另一个相同输入数据的任务。
2.用户发送一个杀死任务请求。
3.任意一个任务运行结束时,YARN会触发一个杀死任务的命令,以释放对应的Container占用的资源。
八 推测执行机制
为了防止执行速度慢的任务拖慢整体的执行进度,使用推测执行机制,Hadoop会为该任务启动一个备份任务,让该备份任务与原始任务同时处理同一份数据,谁先运行完,则将谁的结果作为最终结果。
注:
1.每个任务最多只能有一个备份任务实例
2.启动备份的时候,必须保证已经有足够多的Map任务已经完成,根据这些完成的任务来估算是否来启动备份任务。
这种算法的优点是可最大化备份任务的有效率,其中有效率指有效备份任务数与所有备份任务数的比值,有效任务是指完成时间早于原始任务完成时间的备份任务(即带来实际收益的备份任务)。备份任务的有效率越高,推测执行算法越优秀,带来的收益也就越大。
推测执行机制实际上采用了经典的算法优化方法,以空间换时间,它同时启动多个相同的任务处理相同的数据,并让这些任务竞争以缩短数据的处理时间。