理想情况下,我们应用对Yarn资源的请求应该立刻得到满足,但现实情况资源往往是有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到相应的资源。在 Yarn 中,负责给应用分配资源的就是 Scheduler。其实调度本身就是一个难题,很难找到一个完美的策略可以解决所有的应用场景。为此,Yarn 提供了多种调度器和可配置的策略供我们选择。

在Yarn 中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,Fair Scheduler。

5.4.1 队列调度

FIFO Scheduler 把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。


FIFO Scheduler 是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞。在共享集群中,更适合采用 Capacity Scheduler 或 Fair Scheduler,这两个调度器都允许大任务和小任务在提交的同时获得一定的系统资源。

5.4.2 容量调度

Capacity Scheduler 调度器以队列为单位划分资源。简单通俗点来说,就是一个个队列有独立的资源,队列的结构和资源是可以进行配置的。如总任务 root 下,default 队列占 30% 资源,analyst 和 dev 分别占 40% 和 30% 资源;类似的,analyst 和 dev 各有两个子队列,子队列在父队列的基础上再分配资源。


  • 队列里的应用以 FIFO 方式调度,每个队列可设定一定比例的资源最低保证和使用上限

  • 每个用户也可以设定一定的资源使用上限以防止资源滥用

  • 而当一个队列的资源有剩余时,可暂时将剩余资源共享给其他队列

详细配置参考Capacity Scheduler官方文档

调度器配置

CapacityScheduler 的配置项包括两部分,其中一部分在 yarn-site.xml 中,主要用于配置YARN集群使用的调度器;另一部分在 capacity-scheduler.xml 配置文件中,主要用于配置各个队列的资源量、权重等信息。

  1. 开启调度器

    在ResourceManager中配置使用的调度器,修改yarn-site.xml,设置属性:

<property>
<name>yarn.resourcemanager.scheduler.class</name>   <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>
  1. 配置队列

    调度器的核心就是队列的分配和使用,修改 HADOOP_CONF/capacity-scheduler.xml 可以配置队列。Capacity 调度器默认有一个预定义的队列:root,所有的队列都是它的子队列。队列的分配支持层次化的配置,使用.来进行分割,比如:

yarn.scheduler.capacity.<queue-path>.queues
案例1:root 下有 3 个队列 a、b、c,a 队列下有 2 个队列 a1、a2,b 队列下有 3 个队列 b1、b2、b3

<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>

  1. 队列的属性配置

  • 系统繁忙时,每个队列都应该得到设置的量的资源;当系统空闲时,该队列的资源则可以被其他的队列使用。同一层的所有队列加起来必须是 100%;队列的资源容量占比(百分比):

<property>
   <name>yarn.scheduler.capacity.<queue-path>.capacity</name>
   <value>50</value>
   <description>Default queue target capacity.</description>
</property>
  • 系统空闲时,队列可以使用其他的空闲资源,因此最多使用的资源量则是该参数控制。默认是 -1,即禁用。队列资源的使用上限:

<property>

    <name>yarn.scheduler.capacity.<queue-path>.maximum-capacity</name>

    <value>100</value>

    <description>

      The maximum capacity of the default queue.

    </description>

</property>

每个任务占用的最少资源

<property>

    <name>yarn.scheduler.capacity.<queue-path>.minimum-user-limit-percent</name>

    <value>25</value>

</property>

设置成 25%。那么如果有两个用户提交任务,那么每个任务资源不超过 50%。如果 3 个用户提交任务,那么每个任务资源不超过 33%。如果 4 个用户提交任务,那么每个任务资源不超过 25%。如果 5 个用户提交任务,那么第五个用户需要等待才能提交。默认是 100,即不去做限制

  • 每个用户最多使用的队列资源占比

<property>

    <name>yarn.scheduler.capacity.<queue-path>.user-limit-factor</name>

    <value>0.5</value>

    <description>

      Default queue user limit a percentage from 0.0 to 1.0.

    </description>

</property>

每个用户使用的资源最多就是 50%

  1. 运行和提交应用限制

  • 设置系统中可以同时运行和等待的应用数量,默认是 10000

<property>
   <name>yarn.scheduler.capacity.maximum-applications</name>
   <value>10000</value>
   <description>
    Maximum number of applications that can be pending and running.
   </description>
</property>
  • 设置有多少资源可以用来运行 app master,即控制当前激活状态的应用,默认是 10%。

<property>

    <name>yarn.scheduler.capacity.maximum-am-resource-percent</name>

    <value>0.1</value>

    <description>

      Maximum percent of resources in the cluster which can be used to run

      application masters i.e. controls number of concurrent running

      applications.

    </description>

</property>

<property>

    <name>yarn.scheduler.capacity.<queue-path>.maximum-am-resource-percent</name>

    <value>0.1</value>

    <description>

      Maximum percent of resources in the cluster which can be used to run

      application masters i.e. controls number of concurrent running

      applications.

    </description>

</property>

  1. 队列管理

  • 队列的状态,可以使 RUNNING 或者 STOPPED

<property>
   <name>yarn.scheduler.capacity.<queue-path>.state</name>
   <value>RUNNING</value>
   <description>
    The state of the default queue. State can be one of RUNNING or STOPPED.
   </description>
</property>
  • 访问控制列表 ACL:控制谁可以向该队列提交任务

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

<property>

    <name>yarn.scheduler.capacity.<queue-path>.acl_submit_applications</name>

    <value>*</value>

    <description>

      The ACL of who can submit jobs to the default queue.

    </description>

</property>

限定哪些 Linux 用户/用户组可向给定队列中提交应用程序。如果一个用户可以向该队列提交,那么也可以提交任务到它的子队列。配置该属性时,用户之间或用户组之间用“,”分割用户和用户组之间用空格分割,比如“user1, user2 group1,group2”。

  • 队列的管理员的ACL控制

<property>
   <name>yarn.scheduler.capacity.root.<queue-path>.acl_administer_queue</name>
   <value>*</value>
   <description>
    The ACL of who can administer jobs on the default queue.
   </description>
</property>
  • 映射单个用户或者用户组到一个队列

  1. 基于用户/组的队列映射

为队列指定一个管理员,该管理员可控制该队列的所有应用程序,比如杀死任意一个应用程序等。同样,该属性具有继承性,如果一个用户可以向某个队列中提交应用程序,则它可以向它的所有子队列中提交应用程序,配置该属性时,用户之间或用户组之间用“,”分割用户和用户组之间用空格分割,比如“user1, user2 group1,group2”。

<property>

    <name>yarn.scheduler.capacity.queue-mappings</name>

    <value>u:user1:queue1,g:group1:queue2,u:%user:%user,u:user2:%primary_group</value>

    <description>

      A list of mappings that will be used to assign jobs to queues

      The syntax for this list is [u|g]:[name]:[queue_name][,next mapping]*

      Typically this list will be used to map users to queues,

      for example, u:%user:%user maps all users to queues with the same name

      as the user.

    </description>

</property>

[u or g]:[name]:[queue_name][,next_mapping],列表可以多个,之间以逗号分隔。%user 放在[name]部分,表示已经提交应用的用户。如果队列名称和用户一样,那可以使用 %user 表示队列。如果队列名称和用户主组一样,可以使用%primary_group表示队列。u:%user:%user表示-已经提交应用的用户,映射到和用户名称一样的队列上。 u:user2:%primary_group表示user2提交的应用映射到user2主组名称一样的队列上。如果用户组并不多,队列也不多,建议还是使用简单的语法,而不要使用带%的

  • 针对特定用户的队列是否可以被覆盖,默认值为false

<property>
   <name>yarn.scheduler.capacity.queue-mappings-override.enable</name>
   <value>false</value>
   <description>
    If a queue mapping is present, will it override the value specified
    by the user? This can be used by administrators to place jobs in queues
    that are different than the one specified by the user.
    The default is false.
   </description>
</property>
  • 资源计算方法

  1. 资源配置

<property>

    <name>yarn.scheduler.capacity.resource-calculator</name>

    <value>org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator</value>

    <description>

      The ResourceCalculator implementation to be used to compare

      Resources in the scheduler.

      The default i.e. DefaultResourceCalculator only uses Memory while

      DominantResourceCalculator uses dominant-resource to compare

      multi-dimensional resources such as Memory, CPU etc.

    </description>

</property>

默认是org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator,它只会计算内存。DominantResourceCalculator则会计算内存和CPU。

  • 调度器尝试进行调度的次数

<property>
   <name>yarn.scheduler.capacity.node-locality-delay</name>
   <value>40</value>
   <description>
    Number of missed scheduling opportunities after which the CapacityScheduler
    attempts to schedule rack-local containers.
    When setting this parameter, the size of the cluster should be taken into account.
    We use 40 as the default value, which is approximately the number of nodes in one rack.
    Note, if this value is -1, the locality constraint in the container request
    will be ignored, which disables the delay scheduling.
   </description>
</property>
  1. 修改队列或者调度器的配置capacity-scheduler.xml完成后,需要执行下面的命令使其生效

节点局部性延迟,在容器企图调度本地机栈容器后(失败),还可以错过多少次的调度次数。一般都是跟集群的节点数量有关。默认40(一个机架上的节点数)一旦设置完这些队列属性,就可以在web ui上看到了。

yarn rmadmin -refreshQueues

队列不能被删除,只能新增;

更新队列的配置需要是有效的值;

同层级的队列容量限制相加需要等于100%;

在MapReduce中,可以通过mapreduce.job.queuename属性指定要用的队列。如果队列不存在,在提交任务时就会收到错误。如果没有定义任何队列,所有的应用将会放在一个default队列中

综合案例

需求:root下有两个队列,分别为生产prod队列和开发dev队列,开发队列中有工程师eng和科学家science。


  1. yarn-site.xml追加内容如下:

<property>

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

</property>

  1. 将capacity-scheduler.xml文件备份一份

cp capacity-scheduler.xml capacity-scheduler.xml.bak
  1. capacity-scheduler.xml内容如下

<?xml version="1.0"?>

<configuration>

<!-- 分为两个队列,分别为prod和dev -->  

<property>

<name>yarn.scheduler.capacity.root.queues</name>

<value>prod,dev</value> 

</property>

<!-- dev继续分为两个队列,分别为eng和science -->      

<property>

<name>yarn.scheduler.capacity.root.dev.queues</name>

<value>eng,science</value> 

</property>

<!-- 设置prod队列40% -->      

<property>

<name>yarn.scheduler.capacity.root.prod.capacity</name>

<value>40</value>

</property> 

<!-- 设置dev队列60% -->  

<property>

<name>yarn.scheduler.capacity.root.dev.capacity</name>

<value>60</value> 

</property>

<!-- 设置dev队列可使用的资源上限为75% -->  

<property>

<name>yarn.scheduler.capacity.root.dev.maximum-capacity</name>

<value>75</value> 

</property>

<!-- 设置eng队列50% -->    

<property>

<name>yarn.scheduler.capacity.root.dev.eng.capacity</name>

<value>50</value> 

</property>

<!-- 设置science队列50% -->   

<property>

<name>yarn.scheduler.capacity.root.dev.science.capacity</name>

<value>50</value>

</property>

</configuration>

dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急;

eng和science两个队列没有设置maximum-capacity属性,也就是说eng或science队列中的job可能会用到整个dev队列的所有资源(最多为集群的75%);

而类似的,prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。

对于Capacity调度器,队列名必须是队列树中的最后一部分,如果使用队列树则不会被识别。比如,在上面配置中,使用prod和eng作为队列名是可以的,但是如果用root.dev.eng或者dev.eng是无效的。

  1. 将修改好的配置文件yarn-site.xml、capacity-scheduler.xml分发到集群中所有节点

xsync capacity-scheduler.xml
xsync yarn-site.xml
  1. 关闭yarn集群

stop-yarn.sh
  1. 启动yarn集群

start-yarn.sh
  1. 进入yarn监控界面

http://master:8088

8.仿真模拟数据单词文件,并上传
vi word.txt
内容如下:

hadoop xml mysql

hadoop java xml

mysql hadoop hadoop

hadoop xml hadoop

上传文件到集群:

hdfs dfs -mkdir -put word.txt /user/briup

9.基于pro队列执行作业

yarn jar software/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount     -Dmapreduce.job.queuename=prod /user/briup/word.txt /user/briup/word_result 



  1. 基于dev下eng队列执行作业

yarn jar software/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount    -Dmapreduce.job.queuename=eng /user/briup/word.txt /user/briup/word_result1 



  1. 不指定队列提交作业

yarn jar software/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount     /user/briup/word.txt /user/briup/word_result2


不指定运行队列,默认运行在default队列,如果找不到default队列将会报如上错误。

5.4.3 公平调度

在Fair调度器中,我们不需要预先占用一定的系统资源,Fair调度器会为所有运行的job动态的调整系统资源。如下图所示,当第一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。

需要注意的是,在下图Fair调度器中,从第二个任务提交到获得资源会有一定的延迟,因为它需要等待第一个任务释放占用的Container。小任务执行完成之后也会释放自己占用的资源,大任务又获得了全部的系统资源。最终效果就是Fair调度器即得到了高的资源利用率又能保证小任务及时完成。


公平调度器 Fair Scheduler 最初是由 Facebook 开发设计使得 Hadoop 应用能够被多用户公平地共享整个集群资源,现被 Cloudera CDH 所采用。

Fair Scheduler 不需要保留集群的资源,因为它会动态在所有正在运行的作业之间平衡资源。

详细配置参考Fair Scheduler官网配置

公平调度器了解即可,如需要测试注意配置中内存的设置。内存设置过低,程序会出现卡住。

综合案例

需求:创建两个队列,分别是test和briup(用户所属组命名),对应用户提交作业到指定组队列中

  1. yarn-site.xml追加内容如下:

<property>

  <name>yarn.resourcemanager.scheduler.class</name>

  <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>

</property>

<!--指定公平调度器配置文件路径,该文件名可以随意指定-->

<property>

  <name>yarn.scheduler.fair.allocation.file</name>

  <value>/home/briup/software/hadoop/etc/hadoop/fair-scheduler.xml</value>

</property>

<!--在没有指定队列的情况,是否使用用户名作为队列,如果设置为true,当briup用户提交作业时候,会自动创建使用root.briup队列,-->

<property>

  <name>yarn.scheduler.fair.user-as-default-queue</name>

  <value>true</value>

</property>

<!--是否允许队列之间资源抢占-->

<property>

  <name>yarn.scheduler.fair.preemption</name>

  <value>true</value>

</property>

2.fair-scheduler.xml追加内容如下:

<?xml version="1.0"?>

<allocations>

  <!--单个队列Application Master占用资源的最大比列0-1,企业配置一般0.1-->

  <queueMaxAMShareDefault>0.1</queueMaxAMShareDefault>

  <!--单个队列的最大资源-->

  <queueMaxResourcesDefault>8192 mb,8vcores</queueMaxResourcesDefault>

  <!--增加一个队列-->

  <queue name="root">

    <!--队列最小资源-->

    <minResources>8192 mb,8vcores</minResources>

    <!--队列的最大资源-->

    <maxResources>24578 mb,24vcores</maxResources>

    <!--队列中最多可以运行的应用数,默认50,可以基于线程数配额-->

    <maxRunningApps>10</maxRunningApps>

    <!--队列中Application Master占用的资源最大比列-->

    <maxAMShare>0.1</maxAMShare>

    <!--队列的权重值,值越大越优先获取资源-->

    <weight>1.0</weight>

    <!--队列内部资源分配策略-->

    <schedulingPolicy>fair</schedulingPolicy>

    <!-- 新增一个队列,type=parent为父队列,其下可以设置子队列-->

  <queue name="default">

    <!--队列最小资源-->

    <minResources>8192 mb,8vcores</minResources>

    <!--队列的最大资源-->

    <maxResources>24578 mb,24vcores</maxResources>

    <!--队列中最多可以运行的应用数,默认50,可以基于线程数配额-->

    <maxRunningApps>4</maxRunningApps>

    <!--队列中Application Master占用的资源最大比列-->

    <maxAMShare>0.1</maxAMShare>

    <!--队列的权重值,值越大越优先获取资源-->

    <weight>1.0</weight>

    <!--队列内部资源分配策略-->

    <schedulingPolicy>fair</schedulingPolicy>

      <!--没有指定队列的全部提交到default队列-->

      <aclSubmitApps>*</aclSubmitApps>

  </queue>

    <!-- 新增一个队列,type=parent为父队列,其下可以设置子队列-->

  <queue name="briup">

    <!--队列最小资源-->

    <minResources>2048 mb,2vcores</minResources>

    <!--队列的最大资源-->

    <maxResources>4096 mb,4vcores</maxResources>

    <!--队列中最多可以运行的应用数,默认50,可以基于线程数配额-->

    <maxRunningApps>4</maxRunningApps>

    <!--队列中Application Master占用的资源最大比列-->

    <maxAMShare>0.1</maxAMShare>

    <!--队列的权重值,值越大越优先获取资源-->

    <weight>1.0</weight>

    <!--队列内部资源分配策略-->

    <schedulingPolicy>fair</schedulingPolicy>

      <!--设置可以提交任务的用户名和用户组,格式:用户名,用户名 用户所属组,用户所属组-->

      <aclSubmitApps>briup briup</aclSubmitApps>

      <!--设置管理任务的用户名和用户组可以提交-->

      <aclAdministerApps>briup briup</aclAdministerApps>

  </queue>

  </queue>

</allocations>

  1. 将修改好的配置文件yarn-site.xml、fair-scheduler.xml分发到集群中所有节点

xsync fair-scheduler.xml
xsync yarn-site.xml
  1. 关闭重启yarn集群

stop-yarn.sh

start-yarn.sh



5.不指定队列提交作业

yarn jar software/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount     /user/briup/word.txt /user/briup/word_result2


基于briup用户提交,briup属于briup组,因此作业提交到briup队列中



最后修改: 2023年12月28日 星期四 16:58