作业提交全过程详解
(1)作业提交
第1步:客户端Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业,并且向ResourceManager的ApplicationManager申请一个jobID。
第2步: Application Manager接到申请后给客户端返回该job资源的提交路径和作业id。
第3步: 客户端Client将作业所需要的资源(Jar包、配置信息、切片信息等)上传到返回的HDFS资源提交路径。(切片未来可以控制开启多少个map,配置信息Job.xml未来可以控制我的任务按照我设定的参数运行,jar包是程序代码)
第4步:上传完资源后,向RescourceManager发送请求,申请执行作业。
(2)作业初始化
第5步:当RescourceManager收到客户端的请求后,将请求转发到调度器ResourceScheduler。
第6步:调度器ResourceScheduler会将任务放到调度队列中(先进先出),当执行到相应的请求时,会通知Application Manager分配容器,调用空闲的、存放数据的NodeManager开辟的Container,创建作业对应的ApplicationMaster
第7步:开辟资源Container,启动ApplicationMaster。
第8步:ApplicationMaster获取HDFS上提交的文件(下载Client提交的资源到本地),到时候根据切片信息,创建MapTask和ReduceTask
(3)任务分配
第9步:ApplicationMaster将数据切分成一个个逻辑片,并根据切片数量向调度器ResourceScheduler申请对应的MapTask数(先问它mapper都在什么节点上干活儿)
第10步:RescourceManager上的调度器根据以往所有NodeManager提供的的心跳包信息(你忙不忙、上面有哪些数据),返回执行信息(把任务地址告诉 ApplicationMaster任务在哪几个节点上执行 )
第11步:ApplicationMaster收到信息后通知对应的NodeManager节点开容器Container去做对应的Mapper任务 ,通常MapTask的任务位置就在文件本地,数据在哪里,map就开在哪里,减少数据的shuffle迁移过程
(4)任务运行
第12步:MR向接收到任务的NodeManager发送程序启动脚本,收到任务的 NodeManager分别启动MapTask,MapTask对数据分区排序。
第13步:MrAppMaster等待所有MapTask运行完毕后,向RescourceManager申请容器运行ReduceTask。
第14步:ReduceTask向MapTask获取相应分区的数据。
第15步:程序运行完毕后,MR会向RescourceManager发送请求,申请注销自己释放资源。同时将数据交给客户端
(5)进度和状态更新
YARN中的任务将其进度和状态(包括counter)返回给应用管理器, 客户端每秒(通过mapreduce.client.progressmonitor.pollinterval设置)向应用管理器请求进度更新, 展示给用户。
(6)作业完成
除了向应用管理器请求作业进度外, 客户端每5秒都会通过调用waitForCompletion()来检查作业是否完成。时间间隔可以通过mapreduce.client.completion.pollinterval来设置。作业完成之后, 应用管理器和Container会清理工作状态。作业的信息会被作业历史服务器存储以备之后用户核查。