Hadoop笔记(4)yarn架构介绍

在上一篇介绍mapreduce的文章中,我们简单介绍了mapreduce作业的管理者——MrAppMaster,本文将详细介绍整个mapreduce的启动过程以及Hadoop中的资源调度器——yarn。

1. yarn架构

 Apache Yarn(Yet Another Resource Negotiator的缩写)是Hadoop集群资源管理器系统,Yarn从hadoop 2开始引入,最初是为了改善MapReduce的实现,但是它具有通用性,就是将 JobTracker 的资源调度工作独立了出来、解耦合为一个单独的插件,这也就意味着yarn也可以作为其他分布式计算框架的调度器,如spark等。

yarn-old-mapreduce
图1 Hadoop1的mapreduce结构

Hadoop1的mapreduce架构 JobTracker 负责资源管理,跟踪资源消耗和可用性,作业生命周期管理(调度作业任务,跟踪进度,为任务提供容错),TaskTracker 负责加载或关闭任务,定时报告任务状态。可以发现图1的架构存在如下问题:

  • JobTracker 是 MapReduce 的集中处理点,存在单点故障
  • JobTracker 完成了太多的任务,兼顾资源管理、作业控制和跟踪,造成了过多的资源消耗,当 MapReduce job 非常多的时候,会造成很大的内存开销,成为系统的瓶颈。这也是业界普遍总结出老 Hadoop 的 MapReduce 只能支持 4000 节点主机的上限。
  • 在 TaskTracker 端,以 map/reduce task 的数目作为资源的表示过于简单,没有考虑到 cpu/ 内存的占用情况,如果两个大内存或者CPU消耗的 task 被调度到了一块,很容易出现 OOM。
  • 在 TaskTracker 端,把资源强制划分为 map task slot 和 reduce task slot ,而且它们之间资源不共享,如果当系统中只有 map task 或者只有 reduce task 的时候,会造成资源的浪费,也就集群资源利用率低的问题。
  • 不支持多种计算框架并行。
图2 Hadoop2的yarn结构

在Hadoop2中,将 JobTracker 的资源调度工作独立了出来,这个独立出来的资源管理框架,就是 Yarn。Yarn主要有三个组件:一个全局的资源管理器 ResourceManager、每个节点上的资源管理和监督器 NodeManager 以及单个作业的资源管理和任务监控管家 ApplicationMaster,下面我们分别介绍这三个组件。

1.1 Container

在介绍yarn的三大组件之前,需要先了解yarn中的Container 的概念,因为先了解Container有助于我们更好的理解三个组件。

Container 是 Yarn 对资源做的一层抽象,也是ResourceManager资源调度的基本单元,类似于k8s中的pod(再次印证了很多软件的设计思想都是相通的),就像我们平时开发过程中,会对一些基础操作进行封装,只提供给上层一个调用接口一样,Yarn 对资源的管理也是用到了这种思想。Yarn 将CPU、内存、磁盘、网络带宽等计算资源都封装成为一个个的 Container,所以一个节点可以包含多个Container,在每个节点上Container由NodeManager启动和管理,并被它所监控,但受 ResourceManager 调度。简单地说就是 Container 是一个个的基本作战单位营,NodeManager是团长,管辖很多营,ResourceManager相当于总司令,指挥所有的团。总司令(ResourceManager)只负责指挥调度,所有的团长都要向司令汇报当前队伍的兵力情况:多少营在执行任务,还剩多少营等,总司令根据各团当前的作战能力安排作战任务(task,如maptask、reducetask),例如有一个作战任务需要3个营的兵力,一团还有五个营的兵力,就安排给一团了,这样一团还剩两个营的剩余兵力,但是总司令不会管团里面的作战安排,也不管任务成功与否,具体的任务执行由团长(NodeManager)负责,兵力派遣、补充和回调都由团长安排。例如,一团接到两个任务,分别需要一个营的兵力和三个营的兵力,那么团长就让一营去执行任务1,二三四营去执行任务2,当任务完成以后,团长还要负责把兵力调回原岗位,以便执行下一个任务。一个节点会运行多个Container,但一个Container不会跨节点。其实到这里,已经把ResourceManager、NodeManager和Container的关系、功能都介绍完了。

1.2 ResourceManager

Hadoop 中包含了两个独立的主从架构(Master / Slave)集群:HDFS 和 YARN。前面我们已经介绍了HDFS的主节点守护进程是 NameNode,从节点的守护进程是 DataNode,YARN主节点的守护进程是 ResourceManager,从节点的守护进程是 NodeManager,从结构上看两个集群的结构似乎一一对应,所以很多Hadoop的部署环境都是把 NameNode 和 ResourceManager 部署在同一个节点上,DataNode 和 NodeManager 部署在相同的节点上。

ResourceManager(RM) 负责资源管理,整个系统有且只有一个 RM ,来负责资源的调度。ResourceManager根据程序的需求,调度优先级以及可用资源情况,动态分配特定节点运行应用程序,不关注每个应用程序的状态管理。它与每个节点上的NodeManager和每一个应用程序的ApplicationMaster协调工作。ResourceManager包含了两个主要的组件:定时调度器(Scheduler)以及应用管理器(ApplicationManager)。

(1)Scheduler

从本质上来说,Scheduler就是一种策略,或者说一种算法。当 Client 提交一个任务的时候,它会根据所需要的资源以及当前集群的资源状况进行分配。它只负责向应用程序分配资源,并不做监控以及应用程序的状态跟踪,不保证应用程序的失败或者硬件失败的情况下对task重启,只基于应用程序的资源需求执行其调度功能,其调度的资源那就是Container。Hadoop的MapReduce框架中主要有三种Scheduler:FIFO Scheduler、Capacity Scheduler和Fair Scheduler。

FIFO Scheduler:先进先出,不考虑作业优先级和范围,适合低负载集群,即任务量不大,大家排一支队伍按顺序来,一旦被一个大任务占用资源,其他任务都只能等待,即使后面一个任务只需要一分钟就可以完成。

Capacity Scheduler:将资源分为多个队列,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了,共享集群,又保证每个队列最小资源的使用,即排多个队伍,并行调度。除此之外,队列内部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。一般每个队列的任务不同,例如两个队列,队列1都是需要资源比较少的任务(分配的资源少),队列2都是需要较多资源的大任务(分配的资源多),所以叫做容量调度。apache 版本的 hadoop 默认使用的就是 Capacity Scheduler 调度方式

Fair Scheduler:公平的将资源分给应用(对公平的定义可以通过参数来设置),使得所有应用在平均情况下随着时间得到相同的资源份额,即大家一视同仁。公平调度在也可以在多个队列间工作。不需要预先占用一定的系统资源,Fair调度器会为所有运行的job动态的调整系统资源。当第一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。举个例子,假设有两个用户A和B(在实际环境中,我们一般都会创建多个用户,并为每个用户设置使用资源的上限),他们分别拥有一个队列。当A启动一个job而B没有任务时,A会获得全部集群资源;当B启动一个job后,A的job会继续运行,不过一会儿之后两个任务会各自获得一半的集群资源。如果此时B再启动第二个job并且其它job还在运行,则它将会和B的第一个job共享B这个队列的资源,也就是B的两个job会用于四分之一的集群资源,而A的job仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共享。CDH 默认使用的是 Fair Scheduler 调度方式。

(2)ApplicationManager

负责管理 Client 提交的应用。Scheduler不监控应用程序,监控工作由ApplicationManager完成,ApplicationManager主要负责接收job的提交请求,为应用分配第一个Container来运行ApplicationMaster(每一个应用程序从ApplicationMaster开始,ApplicationMaster本身就是一个container(第0个),一旦启动,ApplicationMaster就会与Resourcemanager协商申请更多的container执行task,在运行过程中,可以动态释放和申请container),还有就是负责监控ApplicationMaster,在遇到失败时重启ApplicationMaster运行的Container。

1.3 NodeManager

NodeManager是ResourceManager 在每台计算节点上的代理,负责container的管理,包括启动和管理应用程序的container生命周期,并监控他们的资源使用情况,并且向 ResourceManager/Scheduler 提供这些资源使用报告。NodeManager管理hadoop集群中每个独立的计算节点,在每个DataNode节点上,我们执行jps都可以看到一个NodeManager进程。

NodeManager在启动时,NodeManager向ResourceManager注册,然后发送心跳包来等待ResourceManager的指令,主要目的是管理resourcemanager分配给它的应用程序container。NodeManager只负责管理自身的Container,它并不知道运行在它上面应用的信息。在运行期,通过NodeManager和ResourceManager协同工作,这些信息会不断被更新并保障整个集群发挥出最佳状态。如果任何运行状况检查失败,则NodeManager会将节点标记为运行状况不佳,并将其传达给ResourceManager,然后ResourceManager停止为该节点分配任务。

1.4 ApplicationMaster

每当 Client 提交一个 Application 时,Hadoop就会新建一个 ApplicationMaster ,由这个 ApplicationMaster 去与 ResourceManager 申请container资源,ResourceManager 根据计算数据位置,尽量分配切片文件所在节点上的container,减少文件传输成本,获得资源后会将要运行的程序发送到container上启动,例如我们的mapreduce程序,然后进行分布式计算。每个应用程序都有自己的ApplicationMaster,负责与ResourceManager协商资源(container)和NodeManager协同工作来执行和监控任务,监控作业进度,负责本作业内的任务的容错。当一个ApplicationMaster启动后,会周期性的向resourcemanager发送心跳报告来确认其健康和所需的资源情况,根据Resourcemanager发来的container信息,ApplicationMaster可以更新它的执行计划以适应资源不足或者过剩,也就是说ApplicationMaster可以动态的调整container资源。这里需要注意ApplicationMaster和ApplicationManager的区别,ApplicationManager负责接收job的提交请求,为应用分配第一个Container来运行ApplicationMaster,并且监控ApplicationMaster,ApplicationMaster可以认为是我们mapreduce任务的管家(前面mapreduce篇我们简单提到了MrAppMaster),而ApplicationManager又是ApplicationMaster的管家。

2. MapReduce调度流程

上一篇文章中我们详细介绍了mapreduce的执行过程和原理,并以wordcount为例,编写了一个mapreduce程序,介绍了mapreduce job的各种配置信息,但是对于mapreduce在Hadoop中的宏观调度我们还没有太多的介绍。本节我们以mapreduce的宏观执行过程为例,介绍yarn的任务调度过程。

图3 mapreduce的调度过程
  1. 客户端向集群提交任务,例如 hadoop jar xxx.jar 提交jar包运行,执行job.waitforCompletion() / job.submit()提交job任务。
  2. 客户端会通过yarn客户端YARNClient(RPC服务)向ResourceManager发送请求,请求运行程序(job)。
  3. ResourceManager收到请求后为job分配一个job id和一个用于提交资源的路径。
  4. 客户端把job资源提交到RM指定的hdfs路径中,主要包括split文件、xml文件、jar文件以及分布式缓存文件等。
  5. 客户端向RM报告,资源提交完毕。
  6. RM初始化job信息,把需要运行的job任务添加到任务队列中。
  7. 根据调度策略(Scheduler),如果排到当前job可以执行,RM(由ApplicationManager完成)会向某个有可用资源的NodeManager派发任务。
  8. NodeManager根据hdfs上的任务信息分配一个Container来运行MrAppMaster(mapreduce中的ApplicationMaster)。
  9. 客户端发送shell命令到NodeManager启动MrAppMaster。
  10. MrAppMaster向RM请求申请资源执行任务。
  11. RM响应MrAppMaster请求,并分配节点资源(会尽量根据文件所在节点,就近分配)。
  12. MrAppMaster将要运行的程序发送到分配的资源节点container上启动maptask。
  13. 在maptask结束后,MrAppMaster在指定节点上启动reducetask,中间具体细节,请参考前一篇mapreduce原理篇。
  14. 任务结束后,MrAppMaster向RM报告注销自己,并请求回收资源,包括MrAppMaster自己所在的container 0。

可以发现,yarn只做程序资源的分配和调度,不参与具体的程序执行逻辑,不仅提高了整个Hadoop的执行效率,也让yarn很好的独立出来,成为很多经典计算框架(如mapreduce、storm、spark等)任务调度工具的选择。

3. MapReduce优化参数

本节我们统一介绍一些关于mapreduce的优化参数:

(1)以下参数可以直接在应用程序中设置:

  • mapreduce.map.memory.mb: 一个Map Task可使用的资源上限(单位:MB),默认为1024。如果Map Task实际使用的资源量超过该值,则会被强制杀死。
  • mapreduce.reduce.memory.mb: 一个Reduce Task可使用的资源上限(单位:MB),默认为1024。如果Reduce Task实际使用的资源量超过该值,则会被强制杀死。

  • mapreduce.map.cpu.vcores: 每个Map task可使用的最多cpu core数目, 默认值: 1。

  • mapreduce.reduce.cpu.vcores: 每个Reduce task可使用的最多cpu core数目, 默认值: 1。

  • mapreduce.map.java.opts: Map Task的JVM参数,你可以在此配置默认的java heap size等参数, e.g:"-Xmx1024m -verbose:gc -Xloggc:/tmp/@taskid@.gc"(@taskid@会被Hadoop框架自动换为相应的taskid), 默认值: ""。

  • mapreduce.reduce.java.opts: Reduce Task的JVM参数,你可以在此配置默认的java heap size等参数, e.g:"-Xmx1024m -verbose:gc -Xloggc:/tmp/@taskid@.gc",默认值: ""。

(2)以下参数应该在yarn启动之前配置在服务器的配置文件中才能生效:

  • yarn.scheduler.minimum-allocation-mb      1024      给应用程序container分配的最小内存

  • yarn.scheduler.maximum-allocation-mb      8192     给应用程序container分配的最大内存

  • yarn.scheduler.minimum-allocation-vcores        1    给应用程序container分配的最大CPU核数

  • yarn.scheduler.maximum-allocation-vcores      32   给应用程序container分配的最小CPU核数

  • yarn.nodemanager.resource.memory-mb   8192 

(3)shuffle性能优化的关键参数,应在yarn启动之前就配置好:

  • mapreduce.task.io.sort.mb   100              shuffle的环形缓冲区大小,默认100m

  • mapreduce.map.sort.spill.percent   0.8    环形缓冲区溢出的阈值,默认80%

(4)容错相关参数:

  • mapreduce.map.maxattempts: 每个Map Task最大重试次数,一旦重试参数超过该值,则认为Map Task运行失败,默认值:4。

  • mapreduce.reduce.maxattempts: 每个Reduce Task最大重试次数,一旦重试参数超过该值,则认为Map Task运行失败,默认值:4。

  • mapreduce.map.failures.maxpercent: 当失败的Map Task失败比例超过该值,整个作业失败,默认值为0。如果你的应用程序允许丢弃部分输入数据,则该值可以设为一个大于0的值,比如5,表示如果有低于5%的Map Task失败(如果一个Map Task重试次数超过mapreduce.map.maxattempts,则认为这个Map Task失败,其对应的输入数据将不会产生任何结果),整个作业仍认为成功。

  • mapreduce.reduce.failures.maxpercent: 当失败的Reduce Task失败比例超过该值为,整个作业则失败,默认值为0。

  • mapreduce.task.timeout: Task超时时间,经常需要设置的一个参数,该参数表达的意思为:如果一个task在一定时间内没有任何进入,即不会读取新的数据,也没有输出数据,则认为该task处于block状态,可能是卡住了,也许永远会卡主,为了防止因为用户程序永远block住不退出,则强制设置了一个该超时时间(单位毫秒),默认是300000。如果你的程序对每条输入数据的处理时间过长(比如会访问数据库,通过网络拉取数据等),建议将该参数调大,该参数过小常出现的错误提示是"AttemptID:attempt_14267829456721_123456_m_000224_0 Timed out after 300 secsContainer killed by the ApplicationMaster."。

(5)效率和稳定性相关参数:

  • mapreduce.map.speculative: 是否为Map Task打开推测执行机制,默认为false。如果为true,若某个maptask迟迟未能执行完毕导致整个任务无法结束,Hadoop会启动一个备份maptask,这两个maptask谁先完成,谁就是这份数据的最终计算结果。

  • mapreduce.reduce.speculative: 是否为Reduce Task打开推测执行机制,默认为false,原理同上。

  • mapreduce.job.user.classpath.first & mapreduce.task.classpath.user.precedence:当同一个class同时出现在用户jar包和hadoop jar中时,优先使用哪个jar包中的class,默认为false,表示优先使用hadoop jar中的class。

  • mapreduce.input.fileinputformat.split.minsize: FileInputFormat做切片时的最小切片大小。

  • mapreduce.input.fileinputformat.split.maxsize: FileInputFormat做切片时的最大切片大小。(切片的默认大小就等于blocksize)

最后,还是那句话,最好的资料永远在官网,打开官网地址,选择自己的Hadoop版本,左侧叶面的底部 Configuration 栏就是详细的配置信息。

参考资料

[1] https://www.w3cschool.cn/hadoop/rh161hda.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值