hadoop yarn Job提交和Shuffle

本文深入解析Hadoop YARN架构下Job提交流程,包括客户端提交、资源管理、任务分配与执行,以及关键的Shuffle过程。阐述MapReduce任务如何从提交到完成,重点讲解Shuffle阶段的Map侧与Reduce侧操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hadoop yarn Job提交和Shuffle

 

1.Job提交

我们开发mr程序然后通过命令来提交jar包:

hadoop jar a.jar FullClassName inputpath outputpath

然后进行MapReduce处理,整个运行过程分为3阶段

1Client端使用命令提交MapReduce jobResourcemanager;

2、Resourcemanager分配NodeManager加载与监控分配的Containers

3、NodeManager通过ApplicationMaster与ResourceManager进行资源的申请及状态的交互,进行MapReduce运行时job的管理

1.1Job 提交过程

job的提交通过调用submit()方法创建一个JobSubmitter实例,并调用submitJobInternal()方法。整个job的提交过程如下:

1、客户端向ResourceManager申请application ID,此ID为该MapReduce的jobId。

2、检查output的路径是否正确,是否已经被创建。

3、计算input的splits。

4、拷贝运行job 需要的jar包、配置文件以及计算input的split 到各个节点。

5、在ResourceManager中调用submitAppliction()方法

 

​​​​​​​1.2Job 初始化过程

1、当resourceManager收到了submitApplication()方法的调用通知后,scheduler开始分配 container,随之ResouceManager告知每个nodeManager管理器来启动applicationMaster进程。

2、由applicationMaster决定如何运行tasks,如果job数据量比较小,applicationMaster便选择将tasks运行在一个JVM中。判断标准:当一个job的mappers数量小于10个,只有一个reducer或者读取的文件大小要小于一个HDFS block时,(可通过修改配置项mapreduce.job.ubertask.maxmaps,mapreduce.job.ubertask.maxreduces以及mapreduce.job.ubertask.maxbytes 进行调整)

3、由于在运行tasks之前的这个环节,applicationMaster将会调用setupJob()方法,随之创建output的输出路径(不管你的mapreduce一开始是否报错,输出路径都会创建)

 

​​​​​​​1.3Task 任务分配和执行

1、接下来applicationMaster向ResourceManager请求containers用于执行map与reduce的 tasks这里map task的优先级要高于reduce task,当所有的map tasks结束后,随之进行sort(这里是shuffle过程后面再说),最后进行reduce task的开始。(这里有一点,当map tasks执行了百分之5%的时候,将会请求reduce,具体下面再总结)

2、运行tasks的是需要消耗内存与CPU资源的,默认情况下,map和reduce的task资源分配为1024MB与一个核, (可修改运行的最小与最大参数配 置,mapreduce.map.memory.mb,mapreduce.reduce.memory.mb,mapreduce.map.cpu.vcores,mapreduce.reduce.reduce.cpu.vcores.)

Task 任务执行

1、这时一个task已经被ResourceManager分配到一个container中,由applicationMaster告知nodemanager启动container,这个task将会被一个主函数为YarnChild的java application运行,但在运行task之前,首先定位task需要的jar包、配置文件以及加载在缓存中的文件。

2、YarnChild运行于一个专属的JVM中,所以任何一个map或reduce任务出现问题,都不会影响整个nodemanager的crash或者hang。

3、每个task将完成的处理数据写入临时文件中。

​​​​​​​1.4 运行进度与状态更新

1、MapReduce是一个较长运行时间的批处理过程,可以是一小时、几小时每个job以及每个task都有一个包含job(running,successfully completed,failed)的状态,以及value的计数器,状态信息及描述信息(描述信息一般都是在代码中加的打印信息)

 

2、当一个task开始执行,它将会保持运行记录,记录task完成的比例,对于map的任务,将会记录其运行的百分比,对于reduce来说可能复杂点,但系统依旧会估计reduce的完成比例。当一个map或reduce任务执行时,子进程会持续每三秒钟与applicationMaster进行交互。

​​​​​​​1.5Job 完成

   最终,applicationMaster会收到一个job完成的通知,随后改变job的状态为successful。最终,applicationMaster与task containers被清空完成历史使命。

 

​​​​​​​2.Shuffle与Sort

  从map到reduce的过程,被称之为shuffle过程,MapReduce使到reduce的数据一定是经过key的排序的.

  当map任务将数据output时,不仅仅是将结果输出到磁盘,它是将其写入内存缓冲区域,并进行一些预分类。

​​​​​​​2.1.The Map Side

1、首先map任务的output过程是一个环状的内存缓冲区,缓冲区的大小默认为100MB(可通过修改配置项mpareduce.task.io.sort.mb进行修改),当写入内存的大小到达一定比例,默认为80%(可通过mapreduce.map.sort.spill.percent配置项修改),便开始写入磁盘。

2、在写入磁盘之前,线程将会指定数据写入与reduce相应的patitions中,最终传送给reduce在每个partition中,后台线程将会在内存中进行Key的排序,(如果代码中有combiner方法,则会在output时就进行sort排序,这里,如果只有少于3个写入磁盘的文件,combiner将会在outputfile前启动,如果只有一个或两个,那么将不会调用)

3、这里将map输出的结果进行压缩会大大减少磁盘IO与网络传输的开销(配置参数mapreduce.map .output.compress 设置为true,如果使用第三方压缩jar,可通过mapreduce.map.output.compress.codec进行设置)

 4、随后这些paritions输出文件将会通过HTTP发送至reducers,传送的最大启动线程通过mapreduce.shuffle.max.threads进行配置。

​​​​​​​2.2.The Reduce Side

1、首先上面每个节点的map都将结果写入了本地磁盘中,现在reduce需要将map的结果通过集群拉取过来,这里要注意的是,需要等到所有map任务结束后,reduce才会对map的结果进行拷贝,由于reduce函数有少数几个复制线程,以至于它可以同时拉取多个map的输出结果。默认的为5个线程(可通过修改配置mapreduce.reduce.shuffle.parallelcopies来修改其个数)

2、这里有个问题,那么reducers怎么知道从哪些机器拉取数据呢? 当所有map的任务结束后,applicationMaster通过心跳机制(heartbeat mechanism),由它知道mapping的输出结果与机器host,所以reducer会定时的通过一个线程访问applicationmaster请求map的输出结果。

3、Map的结果将会被拷贝到reduce task的JVM的内存中(内存大小可在mapreduce.reduce.shuffle.input.buffer.percent中设置)如果不够 用,则会写入磁盘。当内存缓冲区的大小到达一定比例时(可通过mapreduce.reduce.shuffle.merge.percent设置)或 map的输出结果文件过多时(可通过配置mapreduce.reduce.merge.inmen.threshold),将会触发合并 (merged)随之写入磁盘。

4、这时要注意,所有的map结果这时都是被压缩过的,需要先在内存中进行解压缩,以便后续合并它们。(合并最终文件的数量可通过mapreduce.task.io.sort.factor进行配置) 最终reduce进行运算进行输出。

 

<think>我们正在处理用户关于Hadoop作业提交YARN的具体流程的问题。根据提供的引用资料,我们可以构建一个详细的步骤说明。注意,用户要求详细流程,因此我们需要将每一步都解释清楚。 参考引用: [1] 提到:当client向YARN提交作业后,意味着向ResourceManager申请一个ApplicationMaster。RM分配一个ApplicationMaster,并通知相应的NodeManager启动一个container来运行ApplicationMaster。 [2] 提到:客户端通过submitJobInternal方法提交作业,其中会调用submitClient.submitJob提交作业到ResourceManager,并传递作业ID提交目录等信息。 [3] 提到:MRAppMaster(即MapReduce的ApplicationMaster)首先向ResourceManager注册,然后为各个任务申请资源,并监控任务运行状态。 结合这些引用,我们可以将作业提交YARN的流程分为以下几个步骤: 1. **作业提交**:客户端将作业提交YARN集群。 2. **申请ApplicationMaster**:ResourceManager为作业分配一个ApplicationMaster。 3. **启动ApplicationMaster**:ResourceManager与某个NodeManager通信,启动一个Container来运行ApplicationMaster。 4. **ApplicationMaster注册**:ApplicationMaster向ResourceManager注册,以便ResourceManager可以跟踪其状态。 5. **申请任务资源**:ApplicationMaster向ResourceManager申请运行任务(MapReduce任务)所需的资源。 6. **启动任务**:ResourceManager分配资源后,ApplicationMaster与相应的NodeManager通信,启动任务Container。 7. **任务执行与监控**:ApplicationMaster监控任务的执行状态,直到所有任务完成。 8. **作业完成**:ApplicationMaster向ResourceManager注销并关闭,客户端获取作业完成状态。 下面详细描述每个步骤: ### 详细流程步骤 1. **作业提交(Client Submits Job)** - 用户通过客户端(如命令行或API)提交作业,客户端调用`Job.waitForCompletion()`方法(或类似方法)启动提交过程[^2]。 - 客户端执行以下操作: - 检查作业的输入输出路径。 - 计算作业的输入分片(Input Splits)。 - 将作业资源(如JAR文件、配置文件、分片信息)复制到HDFS上的一个目录(称为作业提交目录)[^2]。 - 调用`ResourceManager.submitJob()`方法提交作业(实际调用链为:`Job.submit()` -> `JobSubmitter.submitJobInternal()` -> `YARNRunner.submitJob()`)[^2]。 2. **ResourceManager分配ApplicationMaster(RM Allocates ApplicationMaster)** - ResourceManager收到作业提交请求后,会为该作业分配一个唯一的Application ID,并创建一个`ApplicationMaster`进程(实际上是一个特殊的Container)[^1]。 - ResourceManager将ApplicationMaster的启动命令发送给一个NodeManager(通常选择负载较低的节点)[^1]。 3. **启动ApplicationMaster(Launch ApplicationMaster)** - 被选中的NodeManager启动一个Container(容器),并在该Container中运行ApplicationMaster(对于MapReduce作业,就是`MRAppMaster`)[^1][^3]。 - ApplicationMaster初始化作业状态,并设置必要的跟踪监控。 4. **ApplicationMaster注册(ApplicationMaster Registers with RM)** - ApplicationMaster启动后,会向ResourceManager注册自身,这样ResourceManager就可以通过Web UI或API向用户展示作业状态[^3]。 5. **申请任务资源(ApplicationMaster Requests Resources for Tasks)** - ApplicationMaster根据作业的输入分片数(即Map任务数量)以及Reduce任务数量,向ResourceManager申请资源(Container)[^3]。 - 资源请求包括:每个Container所需的内存、CPU等。 6. **分配资源并启动任务(ResourceManager Allocates Containers and Launches Tasks)** - ResourceManager根据调度策略(如Capacity Scheduler或Fair Scheduler)为ApplicationMaster分配Container(在满足资源请求的NodeManager上)[^3]。 - ApplicationMaster与分配到的NodeManager通信,启动任务Container(每个Container运行一个Map任务或Reduce任务)[^3]。 - 任务执行时,会从HDFS读取输入数据,处理后将结果写入HDFS(或中间数据存储在本地磁盘)。 7. **任务执行与监控(Task Execution and Monitoring)** - ApplicationMaster监控所有任务的执行状态(包括心跳进度更新)[^3]。 - 如果某个任务失败,ApplicationMaster会重新申请资源并重新运行该任务(重试次数有限制)。 8. **作业完成(Job Completion)** - 当所有任务成功完成后,ApplicationMaster向ResourceManager发送作业完成状态,并注销自身[^3]。 - 客户端轮询作业状态,当检测到作业完成时,显示结果并退出。 ### 流程图示意 ```mermaid graph TD A[客户端提交作业] --> B[ResourceManager分配ApplicationMaster] B --> C[NodeManager启动ApplicationMaster Container] C --> D[ApplicationMaster向RM注册] D --> E[ApplicationMaster申请任务资源] E --> F[ResourceManager分配Container] F --> G[NodeManager启动Task Container] G --> H[任务执行] H --> I{所有任务完成?} I -- 是 --> J[ApplicationMaster注销并退出] I -- 否 --> E J --> K[客户端获取作业结果] ``` ### 关键点说明 - **资源管理**:ResourceManager负责整个集群的资源调度,而ApplicationMaster负责单个作业的资源申请任务调度。 - **容错机制**:如果某个任务失败,ApplicationMaster会重新申请资源并重试任务(通常重试4次)。 - **状态监控**:客户端通过轮询ResourceManager或ApplicationMaster来获取作业状态。 ### 相关问题 1. **ApplicationMaster在作业执行过程中承担了哪些具体职责?** 2. **如果作业提交后ResourceManager无法分配ApplicationMaster容器,可能是什么原因?** 3. **如何通过YARN的Web UI监控作业的执行状态?** --- 以上流程基于Hadoop 2.x及更高版本的YARN架构。不同版本的实现细节可能略有差异,但核心流程一致。</think>### Hadoop作业提交YARN的详细流程 以下是Hadoop作业提交YARN的核心步骤(基于MapReduce作业示例): #### 1. **作业提交准备(客户端)** ```mermaid graph LR A[客户端调用job.waitForCompletion] --> B[创建JobSubmitter实例] B --> C[检查输入输出路径] C --> D[计算输入分片InputSplits] D --> E[复制作业资源到HDFS] ``` - 客户端调用`job.waitForCompletion()`触发提交流程 - 计算输入数据的分片信息(如文件块位置、大小) - 将作业JAR包、配置文件、分片元数据上传到HDFS(通常存储在`/tmp/hadoop-yarn/staging`)[^2] #### 2. **申请ApplicationMaster** ```mermaid graph LR F[调用ResourceManager.submitApplication] --> G[RM分配Application ID] G --> H[RM调度器分配Container] H --> I[NM启动AppMaster进程] ``` - 客户端通过`YARNRunner.submitJob()`向ResourceManager(RM)提交申请[^2] - RM分配唯一Application ID,并选择NodeManager(NM)启动Container - Container内启动**MRAppMaster**(作业的主控进程)[^1] #### 3. **AppMaster初始化** ```mermaid graph LR J[MRAppMaster向RM注册] --> K[解析输入分片] K --> L[创建任务对象] L --> M[申请资源] ``` - MRAppMaster向RM注册自身(可通过RM Web UI查看状态)[^3] - 从HDFS加载作业配置分片元数据 - 根据输入分片数量创建MapTask对象(ReduceTask稍后创建) #### 4. **资源申请与任务分配** ```mermaid graph LR N[AppMaster申请Container] --> O[RM调度器分配资源] O --> P[AppMaster启动任务] P --> Q[任务状态心跳监控] ``` - AppMaster向RM发送**Container申请请求**(包含所需CPU/内存) - RM调度器(如Capacity/Fair Scheduler)分配Container资源 - AppMaster通过**NodeManager**启动MapTask/ReduceTask[^3] - 任务执行进度通过心跳机制汇报给AppMaster #### 5. **任务执行与监控** ```mermaid graph TB R[MapTask读取输入数据] --> S[Shuffle阶段] S --> T[ReduceTask输出结果] U[AppMaster监控状态] --> V{所有任务完成?} V --是--> W[清理临时资源] V --否--> U ``` - MapTask处理分配的数据块,输出中间结果 - ReduceTask通过Shuffle获取Map输出,生成最终结果 - AppMaster持续监控任务状态,失败时自动重试(默认重试4次) #### 6. **作业完成** - AppMaster向RM注销应用 - 清理HDFS临时文件 - 客户端轮询获取作业最终状态(成功/失败) ### 关键组件交互 ```mermaid sequenceDiagram participant Client participant RM as ResourceManager participant AM as MRAppMaster participant NM as NodeManager participant HDFS Client->>RM: submitApplication() RM->>NM: allocateContainer(AM) NM->>AM: 启动MRAppMaster AM->>RM: registerApplicationMaster() AM->>HDFS: 加载作业资源 loop 任务调度 AM->>RM: requestContainers() RM->>AM: allocateContainers() AM->>NM: startContainer(Task) NM->>AM: 心跳状态汇报 end AM->>RM: unregisterApplicationMaster() ``` ### 性能优化建议 1. **资源参数调整** ```xml <!-- mapreduce.map.memory.mb --> <!-- mapreduce.reduce.memory.mb --> ``` 2. **启用压缩**(减少Shuffle数据量) ```xml <property> <name>mapreduce.map.output.compress</name> <value>true</value> </property> ``` --- ### ⁉ 相关问题 1. **如何在YARN中查看作业的资源分配详情?** 2. **当MapTask持续失败时,YARN会如何处理?** 3. **如何优化Shuffle阶段的数据传输效率?** 4. **Capacity SchedulerFair Scheduler的主要区别是什么?**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值