YARN调度器(Scheduler)详解

理想状况下,咱们应用对Yarn资源的请求应该马上获得知足,但现实状况资源每每是有限的,特别是在一个很繁忙的集群,一个应用资源的请求常常须要等待一段时间才能的到相应的资源。在Yarn中,负责给应用分配资源的就是Scheduler。其实调度自己就是一个难题,很难找到一个完美的策略能够解决全部的应用场景。为此,Yarn提供了多种调度器和可配置的策略供咱们选择。YARN架构以下:算法

  • ResourceManager(RM):负责对各NM上的资源进行统一管理和调度,将AM分配空闲的Container运行并监控其运行状态。对AM申请的资源请求分配相应的空闲Container。主要由两个组件构成:调度器(Scheduler)和应用程序管理器(Applications Manager)。
  • 调度器(Scheduler):调度器根据容量、队列等限制条件(如每一个队列分配必定的资源,最多执行必定数量的做业等),将系统中的资源分配给各个正在运行的应用程序。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位是Container,从而限定每一个任务使用的资源量。Scheduler不负责监控或者跟踪应用程序的状态,也不负责任务由于各类缘由而须要的重启(由ApplicationMaster负责)。总之,调度器根据应用程序的资源要求,以及集群机器的资源状况,为用程序分配封装在Container中的资源。调度器是可插拔的,例如CapacityScheduler、FairScheduler。(PS:在实际应用中,只须要简单配置便可)
  • 应用程序管理器(Application Manager):应用程序管理器负责管理整个系统中全部应用程序,包括应用程序提交、与调度器协商资源以启动AM、监控AM运行状态并在失败时从新启动等,跟踪分给的Container的进度、状态也是其职责。ApplicationMaster是应用框架,它负责向ResourceManager协调资源,而且与NodeManager协同工做完成Task的执行和监控。MapReduce就是原生支持的一种框架,能够在YARN上运行Mapreduce做业。有不少分布式应用都开发了对应的应用程序框架,用于在YARN上运行任务,例如Spark,Storm等。若是须要,咱们也能够本身写一个符合规范的YARN application。
  • NodeManager(NM):NM是每一个节点上的资源和任务管理器。它会定时地向RM汇报本节点上的资源使用状况和各个Container的运行状态;同时会接收并处理来自AM的Container 启动/中止等请求。ApplicationMaster(AM):用户提交的应用程序均包含一个AM,负责应用的监控,跟踪应用执行状态,重启失败任务等。
  • Container:是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当AM向RM申请资源时,RM为AM返回的资源即是用Container 表示的。YARN会为每一个任务分配一个Container且该任务只能使用该Container中描述的资源。

1. Yarn调度器介绍

1.1. FIFO Scheduler(先进先出调度器)

FIFO Scheduler把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求知足后再给下一个分配,以此类推。FIFO Scheduler是最简单也是最容易理解的调度器,也不须要任何配置,但它并不适用于共享集群。大的应用可能会占用全部集群资源,这就致使其它应用被阻塞。在共享集群中,更适合采用Capacity Scheduler或Fair Scheduler,这两个调度器都容许大任务和小任务在提交的同时得到必定的系统资源。下面“Yarn调度器对比图”展现了这几个调度器的区别,从图中能够看出,在FIFO 调度器中,小任务会被大任务阻塞
apache

 1.2.Capacity Scheduler(容量调度器) 

yarn-site.xml中默认配置的资源调度器。而对于Capacity调度器,有一个专门的队列用来运行小任务,可是为小任务专门设置一个队列会预先占用必定的集群资源,这就致使大任务的执行时间会落后于使用FIFO调度器时的时间。用这个资源调度器,就能够配置yarn资源队列,这个后面后介绍用到。网络

 

1.3. FairS cheduler(公平调度器)

Fair调度器的设计目标是为全部的应用分配公平的资源(对公平的定义能够经过参数来设置)。在上面的“Yarn调度器对比图”展现了一个队列中两个应用的公平调度;固然,公平调度在也能够在多个队列间工做。举个例子,假设有两个用户A和B,他们分别拥有一个队列。当A启动一个job而B没有任务时,A会得到所有集群资源;当B启动一个job后,A的job会继续运行,不过一下子以后两个任务会各自得到一半的集群资源。若是此时B再启动第二个job而且其它job还在运行,则它将会和B的第一个job共享B这个队列的资源,也就是B的两个job会用于四分之一的集群资源,而A的job仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共享。在Fair调度器中,咱们不须要预先占用必定的系统资源,Fair调度器会为全部运行的job动态的调整系统资源。当第一个大job提交时,只有这一个job在运行,此时它得到了全部集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。
a) 公平调度器,就是可以共享整个集群的资源
b) 不用预先占用资源,每个做业都是共享的
c) 每当提交一个做业的时候,就会占用整个资源。若是再提交一个做业,那么第一个做业就会分给第二个做业一部分资源,第一个做业也就释放一部分资源。再提交其余的做业时,也同理。。。。也就是说每个做业进来,都有机会获取资源。架构

 

 

1.4. Fair Scheduler与Capacity Scheduler区别

  • 资源公平共享:在每一个队列中,Fair Scheduler可选择按照FIFO、Fair或DRF策略为应用程序分配资源。Fair策略即平均分配,默认状况下,每一个队列采用该方式分配资源
  • 支持资源抢占:当某个队列中有剩余资源时,调度器会将这些资源共享给其余队列,而当该队列中有新的应用程序提交时,调度器要为它回收资源。为了尽量下降没必要要的计算浪费,调度器采用了先等待再强制回收的策略,即若是等待一段时间后尚有未归还的资源,则会进行资源抢占;从那些超额使用资源的队列中杀死一部分任务,进而释放资源
  • 负载均衡:Fair Scheduler提供了一个基于任务数的负载均衡机制,该机制尽量将系统中的任务均匀分配到各个节点上。此外,用户也能够根据本身的需求设计负载均衡机制
  • 调度策略灵活配置:Fiar Scheduler容许管理员为每一个队列单独设置调度策略(当前支持FIFO、Fair或DRF三种)
  • 提升小应用程序响应时间:因为采用了最大最小公平算法,小做业能够快速获取资源并运行完成

2.Yarn调度器配置

yarn资源调度器是在yarn-site.xml中配置app

2.1. FairScheduler

 Fair Scheduler的配置选项包括两部分:负载均衡

  •  一部分在yarn-site.xml中,主要用于配置调度器级别的参数
  •  一部分在一个自定义配置文件(默认是fair-scheduler.xml)中,主要用于配置各个队列的资源量、权重等信息。

 

2.1.1 yarn-site.xml

yarn-site.xml框架

    <!– scheduler start –>
    <property>
        <name>yarn.resourcemanager.scheduler.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
        <description>配置Yarn使用的调度器插件类名;Fair Scheduler对应的是:org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.allocation.file</name>
        <value>/etc/hadoop/conf/fair-scheduler.xml</value>
        <description>配置资源池以及其属性配额的XML文件路径(本地路径)</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.preemption</name>
        <value>true</value>
        <description>开启资源抢占,default is True</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.user-as-default-queue</name>
        <value>true</value>
        <description>设置成true,当任务中未指定资源池的时候,将以用户名做为资源池名。这个配置就实现了根据用户名自动分配资源池。default is True</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.allow-undeclared-pools</name>
        <value>false</value>
        <description>是否容许建立未定义的资源池。若是设置成true,yarn将会自动建立任务中指定的未定义过的资源池。设置成false以后,任务中指定的未定义的资源池将无效,该任务会被分配到default资源池中。,default is True</description>
    </property>
    <!– scheduler end –>

 

2.1.2 fair-scheduler.xml

假设在生产环境Yarn中,总共有四类用户须要使用集群,production、spark、default、streaming。为了使其提交的任务不受影响,咱们在Yarn上规划配置了四个资源池,分别为production,spark,default,streaming。并根据实际业务状况,为每一个资源池分配了相应的资源及优先级等,default用于开发测试目的.分布式

ResourceManager上fair-scheduler.xml配置以下:oop

<?xml version="1.0"?>
<allocations>
    <queue name="root">
        <aclSubmitApps></aclSubmitApps>
        <aclAdministerApps></aclAdministerApps>
        <queue name="production">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>419840mb,125vcores</maxResources>
            <maxRunningApps>60</maxRunningApps>
            <schedulingMode>fair</schedulingMode>
            <weight>7.5</weight>
            <aclSubmitApps>*</aclSubmitApps>
            <aclAdministerApps>production</aclAdministerApps>
        </queue>
        <queue name="spark">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>376480mb,110vcores</maxResources>
            <maxRunningApps>50</maxRunningApps>
            <schedulingMode>fair</schedulingMode>
            <weight>1</weight>
            <aclSubmitApps>*</aclSubmitApps>
            <aclAdministerApps>spark</aclAdministerApps>
        </queue>
        <queue name="default">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>202400mb,20vcores</maxResources>
            <maxRunningApps>20</maxRunningApps>
            <schedulingMode>FIFO</schedulingMode>
            <weight>0.5</weight>
            <aclSubmitApps>*</aclSubmitApps>
            <aclAdministerApps>*</aclAdministerApps>
        </queue>
        <queue name="streaming">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>69120mb,16vcores</maxResources>
            <maxRunningApps>20</maxRunningApps>
            <schedulingMode>fair</schedulingMode>
            <aclSubmitApps>*</aclSubmitApps>
            <weight>1</weight>
            <aclAdministerApps>streaming</aclAdministerApps>
        </queue>
    </queue>
    <user name="production">
        <!-- 对于特定用户的配置:production最多能够同时运行的任务 -->
        <maxRunningApps>100</maxRunningApps>
    </user>
    <user name="default">
        <!-- 对于默认用户配置最多能够同时运行的任务 -->
        <maxRunningApps>10</maxRunningApps>
    </user>

    <!-- users max running apps -->
    <userMaxAppsDefault>50</userMaxAppsDefault>
    <!--默认的用户最多能够同时运行的任务 -->
    <queuePlacementPolicy>
        <rule name="specified"/> 
        <rule name="primaryGroup" create="false" />
        <rule name="secondaryGroupExistingQueue" create="false" />
        <rule name="default" queue="default"/>
    </queuePlacementPolicy>
</allocations>

参数介绍:测试

  • minResources:最少资源保证量,设置格式为“X mb, Y vcores”,当一个队列的最少资源保证量未知足时,它将优先于其余同级队列得到资源,对于不一样的调度策略(后面会详细介绍),最少资源保证量的含义不一样,对于fair策略,则只考虑内存资源,即若是一个队列使用的内存资源超过了它的最少资源量,则认为它已获得了知足;对于drf策略,则考虑主资源使用的资源量,即若是一个队列的主资源量超过它的最少资源量,则认为它已获得了知足。
  • maxResources:最多可使用的资源量,fair scheduler会保证每一个队列使用的资源量不会超过该队列的最多可以使用资源量。
  • maxRunningApps:最多同时运行的应用程序数目。经过限制该数目,可防止超量Map Task同时运行时产生的中间输出结果撑爆磁盘。
  • weight:资源池权重,主要用在资源共享之时,weight越大,拿到的资源越多。好比一个pool中有20GB内存用不了,这时候能够共享给其余pool,其余每一个pool拿多少,就是由权重决定的
  • aclSubmitApps:可向队列中提交应用程序的Linux用户或用户组列表,默认状况下为“*”,表示任何用户都可以向该队列提交应用程序。须要注意的是,该属性具备继承性,即子队列的列表会继承父队列的列表。配置该属性时,用户之间或用户组之间用“,”分割,用户和用户组之间用空格分割,好比“user1, user2 group1,group2”。
  • aclAdministerApps:容许管理任务的用户名和组;一个队列的管理员可管理该队列中的资源和应用程序,好比可杀死任意应用程序。
  • minSharePreemptionTimeout :最小共享量抢占时间。若是一个资源池在该时间内使用的资源量一直低于最小资源量,则开始抢占资源。
  • schedulingMode/schedulingPolicy:队列采用的调度模式,能够是fifo、fair或者drf。

管理员也可为单个用户添加maxRunningJobs属性限制其最多同时运行的应用程序数目。此外,管理员也可经过如下参数设置以上属性的默认值:

  • userMaxJobsDefault:用户的maxRunningJobs属性的默认值。
  • defaultMinSharePreemptionTimeout :队列的minSharePreemptionTimeout属性的默认值。
  • defaultPoolSchedulingMode:队列的schedulingMode属性的默认值。
  • fairSharePreemptionTimeout:公平共享量抢占时间。若是一个资源池在该时间内使用资源量一直低于公平共享量的一半,则开始抢占资源。

这样,每一个用户组下的用户提交任务时候,会到相应的资源池中,而不影响其余业务。队列的层次是经过嵌套<queue>元素实现的。全部的队列都是root队列的孩子,即便没有配到<root>元素里。Fair调度器中的队列有一个权重属性(这个权重就是对公平的定义),并把这个属性做为公平调度的依据。在这个例子中,当调度器分配集群7.5,1,1,0.5资源给production,spark,streaming,default时便视做公平,这里的权重并非百分比。注意,对于在没有配置文件时按用户自动建立的队列,它们仍有权重而且权重值为1。每一个队列内部仍能够有不一样的调度策略。队列的默认调度策略能够经过顶级元素<defaultQueueSchedulingPolicy>进行配置,若是没有配置,默认采用公平调度。尽管是Fair调度器,其仍支持在队列级别进行FIFO调度。每一个队列的调度策略能够被其内部的<schedulingPolicy> 元素覆盖,在上面这个例子中,default队列就被指定采用fifo进行调度,因此,对于提交到default队列的任务就能够按照FIFO规则顺序的执行了。须要注意,spark,production,streaming,default之间的调度仍然是公平调度。每一个队列可配置最大、最小资源占用数和最大可运行的应用的数量。

Fair调度器采用了一套基于规则的系统来肯定应用应该放到哪一个队列。在上面的例子中,<queuePlacementPolicy> 元素定义了一个规则列表,其中的每一个规则会被逐个尝试直到匹配成功。例如,上例第一个规则specified,则会把应用放到它指定的队列中,若这个应用没有指定队列名或队列名不存在,则说明不匹配这个规则,而后尝试下一个规则。primaryGroup规则会尝试把应用放在以用户所在的Unix组名命名的队列中,若是没有这个队列,不建立队列转而尝试下一个规则。当前面全部规则不知足时,则触发default规则,把应用放在default队列中。
固然,咱们能够不配置queuePlacementPolicy规则,调度器则默认采用以下规则:

<queuePlacementPolicy>
      <rule name="specified" />
      <rule name="user" />
</queuePlacementPolicy>

上面规则意思是除非队列被准确的定义,不然会以用户名为队列名建立队列。还有一个简单的配置策略可使得全部的应用放入同一个队列(default),这样就可让全部应用之间平等共享集群而不是在用户之间。这个配置的定义以下:

<queuePlacementPolicy>
     <rule name="default" />
</queuePlacementPolicy>

实现上面功能咱们还能够不使用配置文件,直接设置yarn.scheduler.fair.user-as-default-queue=false,这样应用便会被放入default 队列,而不是各个用户名队列。另外,咱们还能够设置yarn.scheduler.fair.allow-undeclared-pools=false,这样用户就没法建立队列了。

当一个job提交到一个繁忙集群中的空队列时,job并不会立刻执行,而是阻塞直到正在运行的job释放系统资源。为了使提交job的执行时间更具预测性(能够设置等待的超时时间),Fair调度器支持抢占。抢占就是容许调度器杀掉占用超过其应占份额资源队列的containers,这些containers资源即可被分配到应该享有这些份额资源的队列中。须要注意抢占会下降集群的执行效率,由于被终止的containers须要被从新执行。能够经过设置一个全局的参数yarn.scheduler.fair.preemption=true来启用抢占功能。此外,还有两个参数用来控制抢占的过时时间(这两个参数默认没有配置,须要至少配置一个来容许抢占Container):

minSharePreemptionTimeout
fairSharePreemptionTimeout

若是队列在minimum share preemption timeout指定的时间内未得到最小的资源保障,调度器就会抢占containers。咱们能够经过配置文件中的顶级元素<defaultMinSharePreemptionTimeout>为全部队列配置这个超时时间;咱们还能够在<queue>元素内配置<minSharePreemptionTimeout>元素来为某个队列指定超时时间。

与之相似,若是队列在fair share preemption timeout指定时间内未得到平等的资源的一半(这个比例能够配置),调度器则会进行抢占containers。这个超时时间能够经过顶级元素<defaultFairSharePreemptionTimeout>和元素级元素<fairSharePreemptionTimeout>分别配置全部队列和某个队列的超时时间。上面提到的比例能够经过<defaultFairSharePreemptionThreshold>(配置全部队列)和<fairSharePreemptionThreshold>(配置某个队列)进行配置,默认是0.5。

须要注意的是,全部客户端提交任务的用户和用户组的对应关系,须要维护在ResourceManager上,ResourceManager在分配资源池时候,是从ResourceManager上读取用户和用户组的对应关系的,不然就会被分配到default资源池。在日志中出现”UserGroupInformation: No groups available for user”相似的警告。而客户端机器上的用户对应的用户组可有可无。

 

 每次在ResourceManager上新增用户或者调整资源池配额后,须要执行下面的命令刷新使其生效.

yarn rmadmin -refreshQueues
yarn rmadmin -refreshUserToGroupsMappings

动态更新只支持修改资源池配额,若是是新增或减小资源池,则须要重启Yarn集群.

 

 Fair Scheduer各资源池配置及使用状况,在ResourceManager的WEB监控页面上也能够看到: http://ResourceManagerHost:8088/cluster/scheduler

 

 

Reference:

1.Hadoop多用户资源管理–Fair Scheduler介绍与配置

2.yarn公平调度详细分析

 

2.2 Capacity Scheduler配置(默认配置)

hadoop2.7默认使用的是Capacity Scheduler容量调度器

yarn-site.xml

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.capacity.CapacityScheduler</value>
</property>

Capacity 调度器容许多个组织共享整个集群,每一个组织能够得到集群的一部分计算能力。经过为每一个组织分配专门的队列,而后再为每一个队列分配必定的集群资源,这样整个集群就能够经过设置多个队列的方式给多个组织提供服务了。除此以外,队列内部又能够垂直划分,这样一个组织内部的多个成员就能够共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。

一个job可能使用不了整个队列的资源。然而若是这个队列中运行多个job,若是这个队列的资源够用,那么就分配给这些job,若是这个队列的资源不够用了呢?其实Capacity调度器仍可能分配额外的资源给这个队列,这就是“弹性队列”(queue elasticity)的概念。

在正常的操做中,Capacity调度器不会强制释放Container,当一个队列资源不够用时,这个队列只能得到其它队列释放后的Container资源。固然,咱们能够为队列设置一个最大资源使用量,以避免这个队列过多的占用空闲资源,致使其它队列没法使用这些空闲资源,这就是”弹性队列”须要权衡的地方。

 

假设咱们有以下层次的队列:

root
├── prod
└── dev
    ├── eng
    └── science

下面是一个简单的Capacity调度器的配置文件,文件名为capacity-scheduler.xml。在这个配置中,在root队列下面定义了两个子队列proddev,分别占40%和60%的容量。须要注意,一个队列的配置是经过属性yarn.sheduler.capacity.<queue-path>.<sub-property>指定的,<queue-path>表明的是队列的继承树,如root.prod队列,<sub-property>通常指capacitymaximum-capacity

 

咱们能够看到,dev队列又被分红了eng和science两个相同容量的子队列。dev的maximum-capacity属性被设置成了75%,因此即便prod队列彻底空闲dev也不会占用所有集群资源,也就是说,prod队列仍有25%的可用资源用来应急。咱们注意到,eng和science两个队列没有设置maximum-capacity属性,也就是说eng或science队列中的job可能会用到整个dev队列的全部资源(最多为集群的75%)。而相似的,prod因为没有设置maximum-capacity属性,它有可能会占用集群所有资源。Capacity容器除了能够配置队列及其容量外,咱们还能够配置一个用户或应用能够分配的最大资源数量、能够同时运行多少应用、队列的ACL认证等。

关于队列的设置,这取决于咱们具体的应用。好比,在MapReduce中,咱们能够经过mapreduce.job.queuename属性指定要用的队列。若是队列不存在,咱们在提交任务时就会收到错误。若是咱们没有定义任何队列,全部的应用将会放在一个default队列中。

注意:对于Capacity调度器,咱们的队列名必须是队列树中的最后一部分,若是咱们使用队列树则不会被识别。好比,在上面配置中,咱们使用prod和eng做为队列名是能够的,可是若是咱们用root.dev.eng或者dev.eng是无效的。

2.3 FIFO Scheduler

 yarn-site.xml

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.fifo.FifoScheduler</value>
</property>
相关文章
相关标签/搜索