1) 应用程序客户端
不管是Mapreduce还是spark都会定制自己的YarnClient,用来提交自己的相关任务。
2) ResourceManager、ApplicationMaster、NodeManage、Container
ResourceManager(Master,一个全局的资源管理器): ResourceManager负责整个系统资源的管理和分配,ResourceManager负责对各个NodeManager上的资源进行统一管理和调度,它主要由两个组件构成:调度器(Scheduler)和应用程序管理器(Applications Manager,ASM),调度器根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。需要注意的是,该调度器是一个“纯调度器”,它不再从事任何与具体应用程序相关的工作,比如不负责监控或者跟踪应用的执行状态等,也不负责重新启动因应用执行失败或者硬件故障而产生的失败任务,这些均交由应用程序相关的ApplicationMaster完成。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位用一个抽象概念“资源容器”(Resource Container,简称Container)表示,Container是一个动态资源分配单位,它将内存、CPU、磁盘、网络等资源封装在一起,从而限定每个任务使用的资源量。此外,该调度器是一个可插拔的组件,用户可根据自己的需要设计新的调度器,YARN提供了多种直接可用的调度器,比如Fair Scheduler和Capacity Scheduler等。ASM应用程序管理器负责管理整个系统中所有应用程序,包括应用程序提交、与调度器协商资源以启动ApplicationMaster、监控ApplicationMaster运行状态并在失败时重新启动它等。
ApplicationMaster(每个应用程序特有的ApplicationMaster用户每次提交的任务都会产生):ApplicationMaster则负责单个应用程序的管理,用户提交一个应用程序时,需要提供这个用以跟踪和管理这个程序,它负责向ResourceManager申请资源,并要求NodeManger启动可以占用一定资源的任务,由于不同的ApplicationMaster被分布到不同的节点上,因此它们之间不会相互影响。也就是说:用户提交的每个应用程序均包含1个ApplicationMaster,主要功能包括:(1)与ResourceManager调度器协商以获取资源(用Container表示);(2)将得到的任务进一步分配给内部的任务;(3)与NodeManager通信以启动/停止任务;(4)监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务。
NodeManage(Slave,每台机器上做资源管理):NodeManage的功能是根据container(逻辑概念,表示cpu资源,内存,硬盘资源),运行具体的用户自定义程序,这里ApplicationMaster相当于发送指令需要启动集群中的程序同时发送参数以及相关的配置文件,而NodeManage相当于实际的执行者,也就是处理单个节点上的资源管理和任务管理、处理来自ResourceManager的命令、处理来自ApplicationMaster的命令。
Container:Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当ApplicationMaster向ResourceManager申请资源时,ResourceManager为ApplicationMaster返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。 需要注意的是,Container不同于MRv1中的slot,它是一个动态资源划分单位,是根据应用程序的需求动态生成的。目前,YARN仅支持CPU和内存两种资源,且使用了轻量级资源隔离机制Cgroups进行资源隔离。
3) 短应用与长应用
YARN上的应用按其运行的生命周期的长短分为长应用和短应用(Flink应用与Spark,Mapreduce)。
a.短应用通常是分析作业,作业从提交到完成,所耗时间是有限的,作业完成后,其占用的资源就会被释放,归还给YARN再次分配,
短应用程序是指一定时间内(可能是秒级、分钟级或小时级,尽管天级别或者更长时间的也存在,但非常少)可运行完成并正常退出的应用程序,
比如MapReduce作业、Tez DAG作业等.
b.长应用通常是一些服务,启动后除非意外或人为终止,将一直运行下去。长应用通常长期占用集群上的一些资源,且运行期间对资源的需求也时常变化。
长应用程序是指不出意外,永不终止运行的应用程序,通常是一些服务,比如Storm Service(主要包括Nimbus和Supervisor两类服务),
HBase Service(包括Hmaster和RegionServer两类服务)等,而它们本身作为一个框架提供了编程接口供用户使用。
c. 尽管这两类应用程序作用不同,一类直接运行数据处理程序,一类用于部署服务(服务之上再运行数据处理程序),但运行在YARN上的流程是相同的。
YARN在2.2.0版本以后增强了对长应用的支持。
4) YARN两个阶段运行该应用程序
用户向YARN提交一个应用程序后,YARN将分为两个阶段运行该应用程序:
第一个阶段是启动ApplicationMaster;
第二个阶段是由ApplicationMaster创建应用程序,为它申请资源,并监控它的整个运行过程,直到运行成功。
5) YARN的工作流程可以分为以下几个步骤:
1.用户向YARN提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序(你自己写的
mapreduce或者spark、Flink)等;
2.ResourceManager为该应用程序分配第一个Container(逻辑概念的资源),并与对应的NodeManager通信,要求它根据Container来启动应用程序的ApplicationMaster;
3.ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManager查看应用程序的运行状
态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~8;
4.ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源;
5.一旦ApplicationMaster申请到资源后,则与对应的NodeManager通信,要求其启动任务;
6.NodeManager为任务设置好运行环境(包括环境变量、jar包、二进制程序等---也就是用户自己编写的程序,比如
Mapreduce等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务;
7.各个任务通过某RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运
行状态,从而可以在任务失败时重新启动任务。
在应用程序运行过程中,用户可以随时通过RPC向ApplicationMaster查询应用程序的当前运行状态;
8.应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。
说明:
在单机程序设计中,为了快速处理一个大的数据集,通常采用多线程并行编程,大体流程如下:先有操作系统启动一个主线程,由它负责数据气氛、任务分配、子线程启动和销毁等工作,而各个子线程只负责计算自己的数据,当所有子线程处理完数据后,主线程再退出;
类比理解,YARN上的应用程序运行过程与之非常相近,只不过它是集群上的分布式并行编程。可以将YARN看做一个云操作系统,它负责为应用程序启动ApplicationMaster(相当于主线程),然后再由ApplicationMaster负责数据气氛、任务分配、启动和监控等工作,而由ApplicationMaster启动其他各个Node的Task(相当于子线程)仅负责计算任务,当所有任务计算完成后,ApplicationMaster认为应用程序运行完成,然后退出。
YARN上协议层面的通信动作
上图涉及三个RPC协议:
- ApplicationClientProtocol: Client-RM之间的协议,主要用于应用的提交;
- ApplicationMasterProtocol: AM-RM之间的协议,AM通过该协议向RM注册并申请资源;
- ContainerManagementProtocol: AM-NM之间的协议,AM通过该协议控制NM启动容器。
YARN上程序层面的调用动作
可以看出,客户端的主要作用就是应用的提交和监控应用运行。
程序跟踪
从http://www.cnblogs.com/admln/p/hadoop2-work-excute-submit.html 的
JobSubmitter.java
status = submitClient.submitJob( jobId, submitJobDir.toString(), job.getCredentials());
1 @Override
2 public JobStatus submitJob(JobID jobId, String jobSubmitDir, Credentials ts)
3 throws IOException, InterruptedException {
4
5 addHistoryToken(ts);
6
7 // Construct necessary information to start the MR AM
8 ApplicationSubmissionContext appContext =
9 createApplicationSubmissionContext(conf, jobSubmitDir, ts);
10
11 // Submit to ResourceManager
12 try {
13 ApplicationId applicationId =
14 resMgrDelegate.submitApplication(appContext);
15
16 ApplicationReport appMaster = resMgrDelegate
17 .getApplicationReport(applicationId);
18 String diagnostics =
19 (appMaster == null ?
20 "application report is null" : appMaster.getDiagnostics());
21 if (appMaster == null
22 || appMaster.getYarnApplicationState() == YarnApplicationState.FAILED
23 || appMaster.getYarnApplicationState() == YarnApplicationState.KILLED) {
24 throw new IOException("Failed to run job : " +
25 diagnostics);
26 }
27 return clientCache.getClient(jobId).getJobStatus(jobId);
28 } catch (YarnException e) {
29 throw new IOException(e);
30 }
31 }
其中最重要的语句之一就是
ApplicationSubmissionContext appContext =
createApplicationSubmissionContext(conf, jobSubmitDir, ts);
读注释可知它用于启动AppMaster前构造必要的信息
1 public ApplicationSubmissionContext createApplicationSubmissionContext(
2 Configuration jobConf,
3 String jobSubmitDir, Credentials ts) throws IOException {
4 ApplicationId applicationId = resMgrDelegate.getApplicationId();
5
6 // Setup resource requirements
7 Resource capability = recordFactory.newRecordInstance(Resource.class);
8 capability.setMemory(
9 conf.getInt(
10 MRJobConfig.MR_AM_VMEM_MB, MRJobConfig.DEFAULT_MR_AM_VMEM_MB
11 )
12 );
13 capability.setVirtualCores(
14 conf.getInt(
15 MRJobConfig.MR_AM_CPU_VCORES, MRJobConfig.DEFAULT_MR_AM_CPU_VCORES
16