Yarn的调度队列类型有三种,分别是fifo(默认队列)、fair(公平队列)、capa(容器队列)

值得一提的是以前历史版本中默认队列是fifo,但在2.7以后的默认队列是capa

三种调度队列的区别如下
默认队列,在测试环境下使用,它本质上是单一的一条任务队列,有着所有任务按照提交顺序先进先出的特性,好处在于无需配置,使用简单,容易理解,缺点在于所有任务在统一队列中,每次执行一个任务,任务如果太大会造成整体的阻塞,影响效率
公平队列,在项目中很少有使用,它本质是多个任务队列,且运行资源足够时就启动一个任务,好处在于同一时间每个队列中均有多个任务在执行,缺点也显而易见资源保持在高度使用率状态,容易造成意外
容器队列,是其二者的一个融合队列,它本质同样存在多条任务队列,但默认情况下每个任务队列允许运行的任务个数是可控的,也就是n队列m运行中的模式,缺点在于配置较为繁琐,好处在于我们可以对任务队列做任务隔离,如专门准备一条任务队列来隔离小任务的执行

下面为大家展示如何修改调度队列为capa
首先修改Hadoop的yarn-site.xml配置文件,指定调度队列

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

在指定了调度队列之后我们需要去配置该队列的参数,Hadoop为每个队列单独准备了一个配置文件,capa的配置文件为capacity-scheduler.xml
打开配置文件后我们可以看到,默认情况下只有一个名为default的队列,同时队列的名字也可以让我们在需要的时候通过命令来查看队列的状态

<property>
    <name>yarn.scheduler.capacity.root.queues</name>
    <value>default</value>
    <description>
      The queues at the this level (root is the root queue).
    </description>
</property>

yarn.scheduler.capacity.root.queues中的root指的是一个默认顶级队列,而不是用户名,所有的队列都由他起头,我们默认使用的是它下面一个叫default的子队列,大家或许会觉得别扭,但yarn整体架构就是这样设计的,有兴趣的可以尝试把default删除,只保留顶层root队列并在任务提交时指定提交到root,但是很可能会出问题,也可以尝试不使用root用一个其他的名字,比如yarn.scheduler.capacity.mysch.queues,下面说到的队列名都是这种格式

当然我们可以通过该配置确定队列的个数,在capa队列中可以存在多个一级任务队列,每个一级任务队列可以有二级子队列,且所有的配置对于父子队列有继承特性,如为一个一级队列添加了只属于某个用户的限制,那么这个队列的所有子队列也同时只属于某个用户,配置方式如下

<property>
  <name>yarn.scheduler.capacity.root.queues</name>
  <value>a,b,c</value>
  <description>The queues at the this level (root is the root queue).
  </description>
</property>

<property>
  <name>yarn.scheduler.capacity.root.a.queues</name>
  <value>a1,a2</value>
  <description>The queues at the this level (root is the root queue).
  </description>
</property>

<property>
  <name>yarn.scheduler.capacity.root.b.queues</name>
  <value>b1,b2,b3</value>
  <description>The queues at the this level (root is the root queue).
  </description>
</property>

上面的配置,形成的队列结构如下

root
------a[队列名字]
      |---a1[子队列名字]
      |---a2[子队列名字]
------b[队列名字]
	  |---b1[子队列名字]
      |---b2[子队列名字]
      |---b3[子队列名字]
------c[队列名字]

根据实际配置经验,在配置时最好不要删除default队列,你可以通过配置降低default的存在感,可一旦删除有很多事会出问题,且正常情况下一个队列被配置存在后,后期不用的话就只会配置它的状态停用,而不会通过配置文件删除相关配置,因为会出问题,下面我们来看一下如何对任务队列做详细配置

首先是队列的属性相关

yarn.scheduler.capacity.某队列名.capacity 该配置是队列占总资源容量的占比(百分比),默认100。如可以设置50,代表50%,系统繁忙时,每个队列最大占用总资源的占比,不过当系统空闲时,该队列的资源是可以被其他的队列使用的,后面的配置会说到。值得注意的是同一层的所有队列加起来必须是100%,不可逾越

yarn.scheduler.capacity.某队列名.maximum-capacity 系统空闲时该队列资源被其他队列使用的上限。由于系统空闲时,队列之间可以使用其他队列的空闲资源,因此最多使用的资源量则是该参数控制。默认是100,既100%全部可使用

yarn.scheduler.capacity.某队列名.user-limit-factor 每个用户最多使用的该队列资源占比,该配置是0.0到1的一个范围值,默认值为1,既每个用户使用的资源最多就是100%

第二类是运行和提交任务的限制

yarn.scheduler.capacity.maximum-applications 或者yarn.scheduler.capacity.某队列名.maximum-applications 设置整个系统中或者某个队列可以同时运行和等待的任务总数量。默认是10000

yarn.scheduler.capacity.maximum-am-resource-percent 或者 yarn.scheduler.capacity.某队列名.maximum-am-resource-percent 设置有多少资源可以用来运行app master,即控制当前激活状态的应用。默认是0.1,既10%。

第三类配置为队列管理

yarn.scheduler.capacity.某队列名.state 队列的状态,值为RUNNING或者STOPPED.如果队列是STOPPED状态,那么新应用不会提交到该队列或者子队列。同样,如果root被设置成STOPPED,那么整个集群都不能提交任务了。现有的应用可以等待完成,因此队列可以优雅的退出关闭。

yarn.scheduler.capacity.root.某队列名.acl_submit_applications 控制谁可以向该队列提交任务。如果一个用户可以向该队列提交,那么也可以提交任务到它的子队列,默认*

yarn.scheduler.capacity.root.某队列名.acl_administer_queue 设置队列的管理员,管理员可以控制队列的所有应用程序,如kill等。同样子队列会继承该队列的管理员,默认*

注意:队列管理配置项的值可以有多个用户或者是多个组,一般用逗号隔开,*代表所有,空格代表所有用户都对其没有权限,默认是*

第四类是两个需要配合capa调度器使用的设置

yarn.scheduler.capacity.resource-calculator 资源计算方法,默认是org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator,它只会计算内存,DominantResourceCalculator则会计算内存和CPU

yarn.scheduler.capacity.node-locality-delay 调度器尝试进行调度的次数。一般都是跟集群的节点数量有关。默认40(一个机架上的节点数)

结语

当上面的配置完成后,一定要执行下面的命令,不要直接重启!不直接重启!不要直接重启!重要的事说三遍,如果直接重启yarn就伟了

$HADOOP_YARN_HOME/bin/yarn rmadmin -refreshQueues

运行完成,我们点击yarn web页面的scheduler,就可以看到我们配置的结果

最后对于队列有两点切记:
1、队列一旦配置生效,则后期尽量不要手动配置删除它,如果不需要配置其状态停用即可,否则强行删除会发生未知的问题
2、所有配置均要有效值才可,比如队列资源占比总和只能是100%,不能多出,且这里说的占比总和参考对象是其父级队列