1: yarn 资源调度的定义
2: yarn 资源调度的种类
在Yarn中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,FairS cheduler。
3: FIFO Scheduler
3.1 FIFO Scheduler 介绍
把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配
将所有的Applications放到队列中,先按照作业的优先级高低、再按照到达时间的先后,为每个app分配资源。如果第一个app需要的资源被满足了,如果还剩下了资源并且满足第二个app需要的资源,那么就为第二个app分配资源,and so on。
优点:简单,不需要配置。
缺点:不适合共享集群。如果有大的app需要很多资源,那么其他app可能会一直等待。
上图的示例:有一个很大的job1,它先提交,并且占据了全部的资源。那么job2提交时发现没有资源了,则job2必须等待job1执行结束,才能获得资源执行。
3.2 使用FIFO Scheduler
默认是 FIFO Scheduler, FIFO Scheduler中没有划分队列的概念。
yarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler
3.3 配置参数
FIFO Scheduler不需要配置
4: Capacity Scheduler
4.1 Capacity Scheduler 介绍
Capacity Scheduler主要是为了解决多租户(multiple-tenants)的问题,也就是为了做资源隔离,让不同的组织使用各自的资源,不相互影响,同时提高整个集群的利用率和吞吐量。Capacity Scheduler里面的核心概念或者资源就是队列(queue)。概念理解上很简单,分多个队列,每个队列分配一部分资源,不同组织的应用运行在各自的队列里面,从而做到资源隔离。但为了提高资源(主要是CPU和内存)利用率和系统吞吐量,在情况允许的情况下,允许队列之间的资源抢占。
4.2 使用Capacity Scheduler
yarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler。
Capacity调度器默认有一个预定义的队列——root,所有的队列都是它的子队列。队列的分配支持层次化的配置,使用.来进行分割,比如yarn.scheduler.capacity.<queue-path>.queues.
$HADOOP_HOME/etc/hadoop/capacity-scheduler.xml 增加如下配置:
<property>name>yarn.scheduler.capacity.root.queues</name>value>prod,dev</value></property>
<property><name>yarn.scheduler.capacity.root.dev.queues</name<value>eng,science</value></property>
<property><name>yarn.scheduler.capacity.root.prod.capacity</name<value>40</value></property>
<property><name>yarn.scheduler.capacity.root.dev.capacity</name<value>60</value></property>
<property><name>yarn.scheduler.capacity.root.dev.maximum-capacity</name><value>75</value></property>
4.3 配置参数
4.3.1 队列配置参数
yarn.scheduler.capacity.root.accessible-node-labels
yarn.scheduler.capacity.root.acl_administer_queue 设置队列的管理员的ACL控制,管理员可以控制队列的所有应用程序。同样,它也具有继承性。
yarn.scheduler.capacity.root.acl_submit_applications 访问控制列表ACL控制谁可以向该队列提交任务。如果一个用户可以向该队列提交,那么也可以提交任务到它的子队列
yarn.scheduler.capacity.root.capacity 100 它是队列的资源容量占比(百分比)。应保证每个队列的容量得到满足,而如果每个队列应用程序较少,可将剩余资源共享给其他队列。同一层的所有队列加起来必须是100%。
yarn.scheduler.capacity.root.dataplatform.accessible-node-labels
yarn.scheduler.capacity.root.dataplatform.acl_administer_queue 设置队列的管理员的ACL控制,管理员可以控制队列的所有应用程序。同样,它也具有继承性。注意:ACL的设置是user1,user2 group1,group2这种格式。如果是*则代表任何人。空格表示任何人都不允许。默认是*.
yarn.scheduler.capacity.root.dataplatform.acl_submit_applications
yarn.scheduler.capacity.root.dataplatform.capacity 它是队列的资源容量占比(百分比)。系统繁忙时,每个队列都应该得到设置的量的资源;当系统空闲时,该队列的资源则可以被其他的队列使用。同一层的所有队列加起来必须是100%。
yarn.scheduler.capacity.root.dataplatform.maximum-am-resource-percent 设置有多少资源可以用来运行app master,即控制当前激活状态的应用。默认是10%
yarn.scheduler.capacity.root.dataplatform.maximum-capacity 队列资源的使用上限。由于系统空闲时,队列可以使用其他的空闲资源,因此最多使用的资源量则是该参数控制。默认是-1,即禁用。队列的资源使用上限(百分比)。由于存在资源共享,因此一个队列使用的资源量可能超过其容量,而最多使用资源量可通过该参数限制
yarn.scheduler.capacity.root.dataplatform.ordering-policy fair
yarn.scheduler.capacity.root.dataplatform.ordering-policy.fair.enable-size-based-weight false
yarn.scheduler.capacity.root.dataplatform.priority 0
yarn.scheduler.capacity.root.dataplatform.state RUNNING 队列的状态,可以使RUNNING或者STOPPED.如果队列是STOPPED状态,那么新应用不会提交到该队列或者子队列。同样,如果root被设置成STOPPED,那么整个集群都不能提交任务了。现有的应用可以等待完成,因此队列可以优雅的退出关闭。
yarn.scheduler.capacity..minimum-user-limit-percent 每个任务占用的最少资源。比如,你设置成了25%。那么如果有两个用户提交任务,那么每个任务资源不超过50%。如果3个用户提交任务,那么每个任务资源不超过33%。如果4个用户提交任务,那么每个任务资源不超过25%。如果5个用户提交任务,那么第五个用户需要等待才能提交。默认是100,即不去做限制。
yarn.scheduler.capacity.root.dataplatform.user-limit-factor 每个用户最多使用的队列资源占比,如果设置为50.那么每个用户使用的资源最多就是50%。
4.3.2 capacity抢占配置参数
YARN Capacity Scheduler开启抢占需要配置如下参数:
yarn.resourcemanager.scheduler.monitor.enable 这个选项通知RM来开启monitoring policy;
yarn.resourcemanager.scheduler.monitor.policies 开启抢占模式, 设置monitor policies为org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy
yarn.resourcemanager.monitor.capacity.preemption.monitoring_interval
抢占发生的每轮时间间隔,默认为3秒。每次调用抢占策略(preemption-policy)将会扫描目前正在使用的队列、正在运行的任务以及container,根据这些信息来判断哪个container将会被抢占。
yarn.resourcemanager.monitor.capacity.preemption.max_wait_before_kill
这个时间是当一个container被标记为被抢占到强制杀死该container的时间间隔,单位为毫秒。默认情况下,在强制杀死该container的之前, 将等待15秒让AM释放资源。
yarn.resourcemanager.monitor.capacity.preemption.total_preemption_per_round
每一轮最大的能够抢占的资源的百分比,默认为0.1。例如,集群的内存总量为100G,如果设置为0.1,那么每一轮抢占最多可以抢占10G的资源。
yarn.resourcemanager.monitor.capacity.preemption.max_ignored_over_capacity
指定当一个队列使用的大小超过一个百分比时,这个队列才可以会被抢占。假设这个值为x,那么RM将会等到这个队列的使用量达到configured_capacity*(1 + x)时才会抢占它。默认为0.1。
yarn.resourcemanager.monitor.capacity.preemption.natural_termination_factor
每一轮抢占的所需资源的百分比,通过设置这个参数来减缓回收的速度,避免回收动作过于激进。例如,设置这个参数为0.2,队列A还需要从队列B抢占5G资源,那么第一轮A将从B抢占5*0.2=1G,第二轮将抢占4*0.2=0.8G。默认为0.2。
4.3.3 node label功能
1) node label功能介绍
Node label是将相似特点的节点进行分组的一种途径,application可以指定在哪里运行。现在我们只支持node partition:
一个node只能有一个node partition, 所以一个集群通过node partition被分为多个互斥的子集群。默认的,node都属于DEFAULT分区(partition="")。
目前Node Labels支持以下特性:
Partition cluster - 每个node可以指定一个label,所以集群将会被分为多个小的互斥的partition。
ACL of node-labels on queues - 用户能够设置每个队列可访问的node label,所以只有某些node可以被特定队列访问。
指定可以被队列访问的partition的资源百分比- 用户可以设置像这样的百分比:队列A可以访问具备lable=hbase label的node30%的资源。这样的百分比设置将会与现存的资源管理器保持一致。
在资源请求中指定必需的Node Label,它将会被分配到具有相同label的node。如果没有指定必需的node label,那么资源请求将会被分配到属于DEFAULT partition的node。
可运维性
Node Label和节点的标签映射可以在RM restart中恢复。
Update node labels -更新node label-管理员可以在RM运行过程中更新node、队列的labels。
2) 启用node lable功能
<property> <name>yarn.node-labels.enabled</name>
<value>true</value></property>
<property> <name>yarn.node-labels.fs-store.root-dir</name> <value>hdfs://ns1/system/yarn/node-labels></property>
<property>
<name>yarn.node-labels.manager-class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager</value>
</property>
3) 配置node lable功能
参考资料:https://han-zw.iteye.com/blog/2326433
1) 为 node添加 label
创建标签列表: yarn rmadmin -addToClusterNodeLabels normal,cpu
给节点打标签: yarn rmadmin -replaceLabelsOnNode s3.cxy7.com,normal
yarn rmadmin -replaceLabelsOnNode s4.cxy7.com,cpu
查看HDFS上的标签文件:hadoop fs -ls /system/yarn/node-labels
执行 yarn rmadmin -replaceLabelsOnNode “node1[:port]=label1 node2=label2”,增加label1到node1,label2到node2.如果用户没有指定port,它将会添加到运行在node上的所有NodeManager。
2) 添加队列与标签的匹配关系,修改capacity-scheduler.xml
<!-- 配置dev和product队列可使用的标签资源占比 -->
<property>
<name>yarn.scheduler.capacity.root.dev.accessible-node-labels.normal.capacity</name>
<value>100</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.product.accessible-node-labels.cpu.capacity</name>
<value>100</value>
</property>
</property>
<!-- 配置dev队列可使用的标签 -->
<property>
<name>yarn.scheduler.capacity.root.dev.accessible-node-labels</name>
<value>normal</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.default-node-label-expression</name>
<value>normal</value>
</property>
注意: yarn.scheduler.capacity.<queue-path>.default-node-label-expression 值类似于"hbase",它的意思是:如果提交到队列的application,在其资源请求中没有指定node label,它会使用hbase作为default-node-label-expression。默认值为空,所以application会从没有node label的节点中获取容器。
4.3.4 其他配置参数
yarn.scheduler.capacity.maximum-am-resource-percent 设置最多有多少资源可以用来运行app master,即控制当前激活状态的应用。默认是10%
yarn.scheduler.capacity.maximum-applications 设置系统中可以同时运行和等待的应用数量。默认是10000.
yarn.scheduler.capacity.node-locality-delay 参见6 错失的调度机会数,在这之后CapacityScheduler将会尝试调度本地机架的容器。典型的,应该设置为集群中节点的数量值。默认设置值约等于一个机架的节点数,为40.值为正整数。
yarn.scheduler.capacity.queue-mappings 配置项指定用户/组到特定队列的映射。你可以映射一个用户或者一个用户列表到队列。语法:[u or g]:[name]:[queue_name][,next_mapping]*。这里,u或者g表明这个映射是针对用户还是租的。值u是针对用户,g是针对组。name 表示用户名或者组名。要指定提交应用程序的用户,可以用%user表示。queue_name表示应用程序映射的队列的名称。要指定队列名称与用户名称相同,可以用%user表示。要指定队列名称与用户所属的首要组名相同,可以用%primary_group表示。
yarn.scheduler.capacity.queue-mappings-override.enable 本人true 这个功能用于指定是否用户指定的队列可以被覆盖。这是布尔值,默认为false。
yarn.scheduler.capacity.resource-calculator=org.apache.hadoop.yarn.util.resource.DominantResourceCalculator 资源计算器。资源计算的实现用于在调度器中比较资源。默认如org.apache.hadoop.yarn.util.resource.DefaultResourseCalculator只使用内存,然而DominantResourceCalculator 用主导资源比较多维度资源,例如内存,CPU等等。值为java类名
4.3.5 配置生效
修改队列属性、添加新队列是非常简单的。你需要编辑conf/capacity-scheduler.xml 并运行 yarn rmadmin -refreshQueues
$ vi $HADOOP_CONF_DIR/capacity-scheduler.xml
$ $HADOOP_YARN_HOME/bin/yarn rmadmin -refreshQueues
yarn rmadmin -refreshQueues使变更生效
备注:队列不能删除,只支持队列的新增——更新队列配置应该是一个有效值,例如队列容量在每一个层级应该等于100%。
4.3.6 application 如何指定 node label
1) mapreduce
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.8.4.jar wordcount -D mapreduce.job.node-label-expression="fastcpu" -D mapreduce.job.queuename="etl-ywpt" /hadoop-hadoop-namenode-container-192-168-200-140.log /output
2) spark
./bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --driver-memory 3g --executor-memory 2g --conf spark.yarn.am.nodeLabelExpression=fastcpu --conf spark.yarn.executor.nodeLabelExpression=fastcpu jars/spark-examples.jar 10
5: Fair Scheduler
5.1 Fair Scheduler介绍
公平调度器FairScheduler基于内存来安排公平调度策略。不像Hadoop的默认调度器,它只将任务构造一个应用队列,公平调度器会在不饿死长周期作业的同时,优先让短周期作业先运行完成。在一组用户中共享集群也是合理的。最终,公平调度策略可以和应用优先级结合起来工作,优先级是一组权重值,资源会按照这个权重比例来分配给每个应用。
FairScheduler允许所有的应用按照默认配置运行,同时也支持通过配置文件来限制每个用户每个队列的运行作业数。这对于一个用户必须一次提交成百上千的应用作业是有帮助的。限制运行的应用作业数,不会导致任何的已提交作业失败,只会让这些作业在调度器队列中等待直到某些用户的更早的作业结束。
5.2 使用Fair Scheduler
yarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
5.3 配置Fair Scheduler
配置FairScheduler一般需要配置两个文件。首先调度器相关的选项可以在yarn-site.xml文件中配置。其次,大多数情况下用户希望创建一个分配文件来列出哪些队列用来分配以及对应的权重和容量。这个分配文件会每10秒钟重新加载一次,从而支持运行时配置变更。
5.3.1 yarn-site.xml 中配置
yarn.scheduler.fair.allocation.file 分配文件的路径地址。分配文件是一个XML文件来描述队列和队列的属性以及特定的策略。这个文件必须是一个XML格式的文件。如果配置一个相对路径,那么该文件会在classpath中被搜索到。默认是
。如: /etc/hadoop/conf/fair-scheduler.xml
yarn.scheduler.fair.user-as-default-queue 是否使用用户名关联分配的默认队列名称,如果是false或者未设置,所有的作业都有一个共享的默认队列,叫做default。默认是true。如果队列分配策略在分配文件中配置过,那么这个属性会被忽略。简而言之就是用用户名作为队列。
yarn.scheduler.fair.preemption 开启资源抢占。 默认false。
yarn.scheduler.fair.sizebasedweight 以作业的规模大小作为调度的权值,默认为false。在一个队列内部分配资源时,默认情况下,采用公平轮询的方法将资源分配各各个应用程序,而该参数则提供了另外一种资源分配方式:按照应用程序资源需求数目分配资源,即需求资源数量越多,分配的资源越多。默认情况下,该参数值为false。设置为true时,应用的权重通过1+请求资源内存大小的自然对数来计算。
yarn.scheduler.fair.assignmultiple 是否允许在一次心跳中进行多次容器分配。默认是false
yarn.scheduler.fair.max.assign 如果上个属性设置为true,这个属性明确一次心跳中能分配的最大的容器数。默认是-1,表示没有限制。
yarn.scheduler.fair.allow-undeclared-pools 该属性默认是true ,如果设置成true,yarn将会自动创建任务中指定的未定义过的资源池。设置成false之后,任务中指定的未定义的资源池将无效,该任务会被分配到default资源池中。
yarn.scheduler.fair.update-interval-ms 锁定调度器和重新计算资源分配和需求,检查是否有抢占的时间间隔属性。默认是500m
yarn.scheduler.fair.locality.threshold.node 当应用程序请求某个节点上资源时,它可以接受的可跳过的最大资源调度机会。当按照分配策略,可将一个节点上的资源分配给某个应用程序时,如果该节点不是应用程序期望的节点,可选择跳过该分配机会暂时将资源分配给其他应用程序,直到出现满足该应用程序需的节点资源出现。通常而言,一次心跳代表一次调度机会,而该参数则表示跳过调度机会占节点总数的比例,默认情况下,该值为-1.0,表示不跳过任何调度机会。
yarn.scheduler.increment-allocation-mb:内存规整化单位,默认是1024,这意味着,如果一个Container请求资源是1.5GB,则将被调度器规整化为ceiling(1.5 GB / 1GB) * 1G=2GB。
yarn.scheduler.increment-allocation-vcores:虚拟CPU规整化单位,默认是1,含义与内存规整化单位类似。
5.3.2 自定义中配置fair-scheduler.xml
demo如下:
<?xml version=”1.0″?>
<allocations>
<queue name=”root”>
<minResources>51200mb,50vcores</minResources>
<maxResources>102400mb,100vcores</maxResources>
<maxRunningApps>100</maxRunningApps>
<weight>1.0</weight>
<schedulingMode>fair</schedulingMode>
<aclSubmitApps> </aclSubmitApps>
<aclAdministerApps> </aclAdministerApps>
<queue name=”default”>
<minResources>10240mb,10vcores</minResources>
<maxResources>30720mb,30vcores</maxResources>
<maxRunningApps>100</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>1.0</weight>
<aclSubmitApps>*</aclSubmitApps>
</queue>
<queue name=”businessA”>
<minResources>5120mb,5vcores</minResources>
<maxResources>20480mb,20vcores</maxResources>
<maxRunningApps>100</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>2.0</weight>
<aclSubmitApps>businessA,lxw1234 group_businessA,group_lxw1234</aclSubmitApps>
<aclAdministerApps>businessA,hadoop group_businessA,supergroup</aclAdministerApps>
</queue>
</queue>
</allocations>
参数如下:
(1)minResources:最少资源保证量,设置格式为“X mb, Y vcores”,当一个队列的最少资源保证量未满足时,它将优先于其他同级队列获得资源,对于不同的调度策略(后面会详细介绍),最少资源保证量的含义不同,对于fair策略,则只考虑内存资源,即如果一个队列使用的内存资源超过了它的最少资源量,则认为它已得到了满足;对于drf策略,则考虑主资源使用的资源量,即如果一个队列的主资源量超过它的最少资源量,则认为它已得到了满足。
(2)maxResources:最多可以使用的资源量,fair scheduler会保证每个队列使用的资源量不会超过该队列的最多可使用资源量。
(3)maxRunningApps:最多同时运行的应用程序数目。通过限制该数目,可防止超量Map Task同时运行时产生的中间输出结果撑爆磁盘。
(4)minSharePreemptionTimeout:最小共享量抢占时间。如果一个资源池在该时间内使用的资源量一直低于最小资源量,则开始抢占资源。
(5)schedulingMode/schedulingPolicy:队列采用的调度模式,可以是fifo、fair或者drf。
(6)aclSubmitApps:可向队列中提交应用程序的Linux用户或用户组列表,默认情况下为“*”,表示任何用户均可以向该队列提交应用程序。需要注意的是,该属性具有继承性,即子队列的列表会继承父队列的列表。配置该属性时,用户之间或用户组之间用“,”分割,用户和用户组之间用空格分割,比如“user1, user2 group1,group2”。
(7)aclAdministerApps:该队列的管理员列表。一个队列的管理员可管理该队列中的资源和应用程序,比如可杀死任意应用程序。
管理员也可为单个用户添加maxRunningJobs属性限制其最多同时运行的应用程序数目。此外,管理员也可通过以下参数设置以上属性的默认值:
(1)userMaxJobsDefault:用户的maxRunningJobs属性的默认值。
(2)defaultMinSharePreemptionTimeout:队列的minSharePreemptionTimeout属性的默认值。
(3)defaultPoolSchedulingMode:队列的schedulingMode属性的默认值。
(4)fairSharePreemptionTimeout:公平共享量抢占时间。如果一个资源池在该时间内使用资源量一直低于公平共享量的一半,则开始抢占资源。
6: 延时调度
当应用程序请求在某个特定的节点上运行时,如果该节点刚好处于忙碌状态无法分配给应用,一种选择方式是就近选择同一机架中的其他节点。但是在实际中发现,稍微等一小段时间,很有可能就能够分配到指定的节点,进而提高集群效率。这个特性叫延迟调度(delay scheduling)。Capacity Scheduler和FairScheduler支持这个特性。
默认情况下,集群中的NodeManager每一秒中都想RM发送心跳,心跳张包含节点当前正在运行的Container以及可用于新Container的资源。因此每次心跳都是一个调度机会(scheduling opportunity)。当启用延迟调度时,对于有节点位置要求的资源请求,调度器不会简单地使用第一次调度机会(牺牲数据locality),而是会尝试等待直到最大次数的调度机会,一旦发现符合要求的调度机会,及分配给应用。如果直到最大次数还是没有合适的节点资源,则放宽数据locality要求,退而求其次采用同一机架。
最大opportunity数的配置,在Capacity Scheduler中使用yarn.scheduler.capacity.node-locality-delay配置,取值为正整数。Fair Scheduler略有不同,配置的是yarn.scheduler.fair.lcality.threshold.node属性,例如设为0.5,代表要等待集群中一半的节点发送心跳提供scheduling opportunity,才决定是否放宽要求采用同一机架上的其他节点。对应的yarn.scheduler.fair.lcality.threshold.rack配置放弃同一机架要求采用不同机架上的机器之前,需要等待多少节点发送心跳。
延时调度参考资料: 原文:https://blog.csdn.net/bingduanlbd/article/details/52000151
7: capacity 和 fair Sechdule 两种区别
7.1 capacity 和 fair Sechdule的区别
两者的调度策略不同:
参考资料:https://www.jianshu.com/p/fa16d7d843af
在 Capacity Scheduler 中,在比较资源占用率时,不同的资源比较器对资源定义是不一样的。默认的是 DefaultResourceCalculator,它只考虑内存资源。另外一种是 DominantResourceCalculator,采用了 DRF 比较算法,同时考虑内存和 cpu 两种资源。通过参数yarn.scheduler.capacity.resource-calculator来设置。
Fair Scheduler 与 Capacity Scheduler 一样也是依次选择队列、应用,最后选择 Container,其中选择队列和应用策略相同,采用了 FairShareComparator 比较器对队列或者应用程序进行排序,然后从头从头开始选择。
在介绍具体实现前还需介绍以下两个定义:
最小共享量:管理员可给每个队列配置一个最小共享量,调度器在分配资源时,需要保证每个队列中的作业至少获取该数目的资源。一个常见的应用场景是,对产品队列设置最小共享量,而测试队列不设置,这样,当可用资源有限时时,优先保证产品队列有资源可用。
公平共享量:当集群中存在多个队列时,某些队列中的资源可能用不了,这时候调度器会自动将这些队列中剩余的资源共享给其他需要的队列,其他这些队列获取的共享资源多少主要由其队列 weight决定,队列 weight越大,获取的资源越多。 一个队列的最小共享量加上其获取的共享资源数目,就是公平共享量。
假设为 s1,s2,公平调度算法流程如下:
若 s1紧需资源(使用资源量小于最小资源保证即紧需资源),s2 紧需资源,把资源给 s1
若 s2紧需资源,s1 不紧需资源,把资源给 s2
若 s1、s2 都紧需资源,把资源给 minShareRatio 更小的,minShareRatio1 = 已使用内存/ 最小资源保证
若 s1、s2 都不紧需资源, 把资源给 useToWeightRatio 更小的, useToWeightRatio = 已使用内存 / 权重
若 s1、s2 都不紧需资源且useToWeightRatio相同,把资源给更早启动的
知道了比较算法,也就知道如何选出队列和应用程序了。选出应用程序之后,选择 Container 的逻辑与Capacity Scheduler 一致。
7.2 capacity 和 fair Sechdule 抢占的区别
capacity 和 fair Sechdule 都支持资源抢占。
fair Sechdule
我们在yarn的管理页面里面,经常可以看到队列的Instantaneous Fair Share以及Steady Fair Share值.想要对Yarn的FairScheduler队列资源管理、以及抢占规则有正确的理解,必须知道Yarn的Fair Share的含义
Steady FairShare是一个队列的理想值,这个值是由集群资源和weigths计算出来的,并不会被经常计算,只是在集群启动或者集群的总资源发生增减的时候才会被重新计算。每个队列的Steady FairShare的计算公式是`totalResources(集群总资源)/weights(所有队列的weight总和)weight(某个队列的weight)`*
Instantaneous FairShare计算集群中每个active队列的FairShare。Steady FairShare是计算集群中所有的队列。这两者的区别为:
空队列也就是没有分配任何资源的队列不会计算Instantaneous FairShare,其值为0。
如果集群中所有的队列都是active,则Steady FairShare和Instantaneous FairShare相等。
每个队列的Instantaneous FairShare的计算公式是`totalResources(集群总资源)/activeWeights(active队列的weight总和)activeWeight(active队列的weight)`*
抢占逻辑:
* 基于已经计算好的需要抢占的资源(toPreempt()方法)进行资源抢占。每一轮抢占,我们从root 队列开始,
* 一级一级往下进行,直到我们选择了一个候选的application.当然,抢占分优先级进行。
* 依据每一个队列的policy,抢占方式有所不同。对于fair policy或者drf policy, 会选择超过
* fair share(这里的fair scheduler都是指Instantaneous Fair Share)
* 最多的ChildSchedulable进行抢占,但是,如果是fifo policy,则选择最后执行的application进行
* 抢占。当然,同一个application往往含有多个container,因此同一个application内部container
* 的抢占也分优先级
yarn.scheduler.fair.waitTimeBeforeKill,默认是15000ms。等待时间超过此值时,将抢占队列中的containerkill掉。
yarn.scheduler.fair.preemptionInterval,默认是5000ms,两次抢占检查的时间间隔
7.3 container 被抢占kill的过程
1)为了尽可能避免资源浪费,YARN优先选择优先级低的Container作为资源抢占对象,且不会立刻杀死Container,而是将释放资源的任务留给应用程序自己:ResourceManager将待杀死的Container列表发送给对应的ApplicationMaster,以期望它采取一定的机制自行释放这些Container占用的资源,比如先进行一些状态保存工作后,再将对应的Container杀死,以避免计算浪费,如果一段时间后,ApplicationMaster尚未主动杀死这些Container,则ResourceManager再强制杀死这些Container
2)NodeManager也可以在ResourceManager的指示下,杀掉Container。当处于下面的几种场景中时,NodeManager就可能Kill掉一个Container:
ResourceManager告诉它,Application已经完成了
Scheduler决定抢占这个Container,并将它分配给另一个Application或者用户
NodeManager检测到,这个Container使用的资源已经超过了ContainerToken中指定的那些资源的限制
yarn.resourcemanager.scheduler.classorg.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler