标签:
在理想国度,YARN应用发送的请求可以立即得到响应。在现实世界中,资源是有限的,在一个
繁忙的集群上,一个应用经常需要等待它的一些请求处理完成。根据预定义的方针分配资源给应用程序是
YARN scheduler的工作。调度通常是一个难点,没有“最好”的方针,它是YARN为什么提供可选调度器
及可配的方针。接下来我们来了解它。
scheduler选项
YARN有三种scheduler:FIFO,Capacity,Fair。FIFO scheduler把应用放在一个队列中,根据他
们的提交顺序运行(先进先出)。队列中第一个应用的请求先分配;一旦它的请求得到满足,队列中的
下一个应用会被处理,以此类推。
FIFO scheduler的优点是简单易懂零配置,但是不适用于共享集群。大的应用会使用集群中的所有
资源,所以所有应用必须等待。在共享集群上最好使用capacity scheduler或fair scheler。这两个都允许
需要长时间运行的job可以及时完成,同时允许用户并行运行一个小的查询并在合理时间内得到返回结果。
这三个scheduler的不同点见图4-3,它展示了在FIFO scheduler(i) 中,小的job被阻塞直到大的job
结束。
使用Capacity Scheduler(ii)时,一个专门的独立的队列允许小的job在提交之后马上开始,它
是以利用整体集群为代价的,因为需要预留资源给它。这意味着大型job结束比使用FIFO要晚。
使用Fair Scheduler(iii)时,它不需要预留资源,因为他会自动在运行的job之间平衡资源。当开始第一个
job后,这是唯一一个运行的job,所以它得到了集群中的所有资源。当第二个job开始,它会得到集群一半的
资源,所以每一个job使用平分的资源。
注意,在job开启与它得到它的资源之间有延迟,因为它需要等待资源释放。当job执行结束不再需要资源
时,另一个job回来继续使用集群的所有资源。整体效果是集群的高利用及小的job的及时完成。
图4-3比较了这三个调度器的基础操作。在再两节中,我们解释更多的Capacity和Fair的高级配置。
Capacity Scheduler配置
Capacity Scheduler通过组织来共享HADOOP集群,每一个组织分配一定容量的集群资源。每一个组织
建立一个专门的队列,并使用一个小数来配置使用的集群容量。队列可能进一步分层,在组织内允许在不同
用户组之间共享集群。在一个队列中,应用的调度使用FIFO。
正如我们在图4-3中看到的,一个单独的job不可能使用比它的队列更多的资源。尽管如此,如果队列中
有多个job,并且有空闲资源,那么Capacity Scheduler可能会把空闲资源分配给队列中的job,尽管这会导致
队列容量超出。这个行为就是众所周知的queue elasticity(队列弹性)。
正常操作中,Capacity Scheduler不会强制终止container来获得它,所以如果一个queue由于没有请求
而导致容量降低,然后请求增加,它只能随着其它container处理完毕后释放资源,容量才能回到正常水平。
可以通过配置queue的最大容量来缓解这个问题,配置最大容量后,queue不会占用太多其它queue的容量。
这是queue elasticity的代价,当然,要通过不断的实验来找到一个合理的权衡值。
设想一个queue的层级看起来是这样:
root
├── prod
└── dev
├── eng
└── science
例4-1显示了一个这个层级的Capacity Scheduler配置文件样本,叫做capacity-scheduler.xml。它在root queue
下定义了两个queue,prod和dev,分别占40%和60%的容量。注意,一个特定的queue通过yarn.scheduler.capacity.
<queue-path>.<sub-property>的形式来设置配置属性,<queue-path>是以点来分隔的层级路径,例如root.prod。
Example 4-1. A basic configuration file for the Capacity Scheduler <?xml version="1.0"?> <configuration> <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> <property> <name>yarn.scheduler.capacity.root.dev.eng.capacity</name> <value>50</value> </property> <property> <name>yarn.scheduler.capacity.root.dev.science.capacity</name> <value>50</value> </property> </configuration>正如你看到的,dev queue进一步分成了eng和science queue,并有一样的容量。dev有一个最
大容量75%,所以当prod queue空闲时,dev queue不会占用所有的集群资源。换句话说,prod queue
始终有25%的集群资源可以立即使用。由于其它queue没有配置最大容量,所以eng或science queue
中的job可能占用所有的dev queue的容量(集群的75%),或者,prod queue占用整个集群。
除了配置queue层级和容量,还有一些设置用来控制某个用户或应用可以分配的最大资源数,在同
一时间可以运行的应用数,以及queue ACL。详细请看参考页。
queue定位
指定应用入放置在哪个queue,不同的应用有不同的方式。例如,mapreduce,你设置属性mapreduce.
job.queuename为你想要使用的queue名称。如果queue不存在,那么你在提交时会得到一个错误。如果没有
配置queue,应用会被放置在一个叫default的queue中。
Fair Scheduler配置
Fair Scheduler尝试分配资源时,所有运行中的应用得到的资源的相同的。图4-3显示了如何平分给在同
一个quueu中的应用;然而,平分通常是在queue之间的,后面我们会看到。
为了了解queue之间如何共享资源,设想两个用户A和B,各自有自己的queue(图4-4)。A开启了一个job,
由于B没有请求,所以它获得了所有的资源。然后在A的job还在运行时,B开启了一个job,一段时间后,每一个
job使用了一半的资源,以我们早些时候看到的方式。现在,如果B开启了第二个job,它会同B的其它job一起
分享资源,所以B的每一个job占有四分之一个资源,而A继续占有一半的资源。结果是资源的用户之间平分。
启用Fair Scheduler
使用哪个sheduler由配置yarn.resourcemanager.scheduler.class决定。默认使用Capacity Scheduler(有些HADOOP默认
使用Fair Scheduler,例如CDH),但是可以设置yarn-site.xml中的yarn.resourcemanager.scheduler.class来改变,它的值是
scheduler类的全路径,org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler。
Queue配置
Fair Scheduler通过类路径中的一个叫fair-scheduler.xml的配置文件来配置(可能通过设置yarn.scheduler.fair.allocation.file来
改变文件名称)。如果没有配置文件,那么Fair Scheduler的操作如前文所述:每一个应用放置在用户
提交它的第一个应用时动态创建的queue中。
每一个queue的配置都定义在配置文件中。这样可以配置层级queue,就像Capacity Scheduler支持的一样。例如,我们可以定义
prod和dev queue,就像我们在Capacity Scheduler中做的一样,如例4-2所示:
Example 4-2. An allocation file for the Fair Scheduler <?xml version="1.0"?> <allocations> <defaultQueueSchedulingPolicy>fair</defaultQueueSchedulingPolicy> <queue name="prod"> <weight>40</weight> <schedulingPolicy>fifo</schedulingPolicy> </queue> <queue name="dev"> <weight>60</weight> <queue name="eng" /> <queue name="science" /> </queue> <queuePlacementPolicy> <rule name="specified" create="false" /> <rule name="primaryGroup" create="false" /> <rule name="default" queue="dev.eng" /> </queuePlacementPolicy> </allocations>通过嵌套的queue元素来定义queue层级。所有的queue都是root queue的子元素,即使没有嵌套在一个root queue元素中。这
里我们把dev queue细分成两个queue,一个eng,另一个science。
queue可以有权重,它用于分配计算。在这个例子中,认为集群在prod和dev之间按照40:60的比例分配是公平的。eng和science
queue没有定义权重,所以它们之间平均分配。权重不一定是百分比,尽管例子中为了简便起见把他们的和加起来等于100.我们可以定义
权重为2和3来达到同样的目的。
queue可以有不同的调度策略。queue默认策略可以通过顶层元素defaultQueueSchedulingPolicy来设置;如果省略,则使用fari scheduler,
fair scheduler也支持FIFO 策略,以及Dominant Resource Fairness,本章稍后会讲解。对于一个特定的queue,可以通过使用schedulingPolicy
元素来覆盖全局变量。在这种情况下,prod queue使用FIFO scheduler,因为我们希望每一个job都是有序并在最短时间内执行完毕。注意,
在prod和dev queue之间,还是使用fair share来分配资源,在eng和science queue之间(及内部)也是如此。
尽管这个配置文件没有显示,queue可以配置最小及最大资源,及最多运行应用数量。最小资源设置不是硬性的,而是scheduler用来区分
资源分配优先级。如果两个queue都比它们的平分值要低,那么期中比它的最小值要低的多的先分配资源。最小资源设置也可以用来强制占有,
稍后讨论。
queue定位
Fair Scheduler使用基于规则的系统来决定一个应用放置在哪个queue。例4-2中,queuePlacementPolicy元素包含了一些规则,每一个
都轮流尝试直到有一个匹配。第一个规则,spcified,把应用放置在它定义的queue中;如果没有定义,或是家底的queue不存在,那么这条
规则不匹配,尝试下一条规则。primaryGroup规则试图把应用放置在用户的用户组名对应的queue中,如果没有,不会创建,而是尝试下一
条规则。缺省规则(default)会把所有应用放置在dev.eng queue。
queuePlacementPolicy可以完全省略,这种情况下的默认行为和如下的定义一样:
<queuePlacementPolicy> <rule name="specified" /> <rule name="user" /> </queuePlacementPolicy>换句话说,除非显示定义了queue,用户名将做为queue,如有必要将创建它。
另一个简单的queue放置策略是把所有应用放置在同一个queue中。这样允许在应用之间平分资源,而不是用户之间。定义和下面的是
等价的:
<queuePlacementPolicy> <rule name="default" /> </queuePlacementPolicy>可以通过设置yarn.scheduler.fair.user-as-default-queue为false来把应用放置在缺省queue而不是per-user queue,这样就不需要使用
上文中的配额文件。另外,需要把yarn.scheduler.fair.allow-undeclared-pools设置为false,这样用户不能动态创建queue。
Preemption
当一个job提交到一个繁忙的集群上的一个空的queue时,这个job不能立即开始,直到资源从已经在集群上运行的job中释放出来。为了
使job开启时间更可控,fair scheduler支持Preemption。
Preemption允许scheduler终止超出它平分资源的queue运行的container,这样资源可以分配给低于平分资源的queue。注意,Preemption
会降低集群的整体效率,因为终止的container需要重新执行。
Preemption可以通过设置全局的yarn.scheduler.fair.preemption为true来开启。有两个相关的preemption超时设置:一个用来保证
minimum share,一个用来保证fair share,这两个定义都是秒为单位。默认情况下,超时是不设置的,所以你至少要设置一个来允许把
container给preempt。
如果一个queue等待了minimum share preemption timeout那么长时间还没有得到最低保证的资源,那么scheduler可能preempt其它
的container。可以通过顶级元素defaultMinSharePreemptionTimeout来设置所有的queue的缺省超时时间,在一个queue中可以通过元素
minShare PreemptionTimeout来设置这个queue的超时时间。
同样,如果一个queue在等待了fair share preemption timeout那么长时间之后还是低于fair share的一半,那么scheduler可能preempt
其它的container。可以通过顶级元素defaultFairSharePreemptionTimeout来设置所有queue的缺省超时时间,在一个queue中可以通过元素
fairSharePreemptionTimeout来设置这个queue的超时时间。这个临界值也可以通过设置defaultFairSharePreemptionThreshold和
fairSharePreemptionThreshold (per-queue)来改变。
延迟调度
所有的YARN scheduler尽量满足位置请求。在一个繁忙的集群上,如果一个应用请求一个特定的节点,很有可能有另一个container正
在上面运行。明显的做法是把请求放宽,并分配同一个rack上的container。但是在实际中发现,如果等待较短的时间(不超过几秒),分配
到请求的那个节点的机会剧增,这样会提高集群的效率。这个特性叫延迟调度,Capacity Scheduler 及 the Fair Scheduler都支持这个特性。
YARN 管理的每一个节点都会周期性的发送心跳请求给资源管理器----默认每秒发送一次。心跳携带node manager的运行中container及
可分配资源的信息,所以每一个心跳都是一个应用运行的机会。
当使用延迟调度时,scheduler不是简单的使用它接收到的第一个调度机会,而是在放宽请求之前等待一个给定的调度机会的最大值并
并取得下一个调度机会。
对于Capacity Scheduler,延迟调度通过设置yarn.scheduler.capacity.node-locality-delay为一个正整数来表示在放宽节点约束为同rack
的任意节点之前,它打算漏掉的调度机会数量。
Fair Scheduler也使用调度机会数来延迟,尽管它表示为集群大小的比例。例如,设置yarn.scheduler.fair.locality.threshold.node为0.5
意味着scheduler在接受同rack的节点之前,至少有一半的节点提供了调度机会。还有一个类似的属性,yarn.scheduler.fair.locality.threshold.rack,
是设置在接受另一个rack的临界值。
Dominant Resource Fairness
当只有单一类型的资源需要调度时,例如内容,那么容量或公平的概念是很好确定的。如果有两个用户运行应用,你可以衡量这两
个应用使用的内容数量。然而,当有多种类型的资源时,事情就变得复杂了。如果一个用户的应用需要很多的CPU及很少的内容,而另
一个需要很少的CPU及大量的内容,这两个应用该如何比较呢?
YARN的scheduler解决这个问题是方式是查看用户的显性资源并用它来衡量集群的使用。这种方式叫做Dominant Resource Fairness,
简称DRF。最好通过一个例子来说明。
设想一个集群有100个CPU及10TB内存。应用A请求container(2个CPU,300GB),应用B请求container(6个CPU,100GB)。A的请求占用
(2%,3%)的集群,所以内容是显性的,因为它的比例(3%)大于CPU的比例(2%)。B的请求(6%,1%),所以CPU是显性。因为
B的显性container请求是A的两倍(6%比3%),分配给它的container数量是平分的一半。
默认是不使用DRF的,所以在资源计算时,只考虑内容,而CPU忽略了。Capacity Scheduler可以通过设置capacity-scheduler.xml中的
yarn.scheduler.capacity.resource-calculator为org.apache.hadoop.yarn.util.resource.DominantResourceCalculator来使用DRF。
对于Fair Scheduler,可能通过设置顶级元素defaultQueueSchedulingPolicy为drf来启用DRF。
标签:
原文地址:http://blog.csdn.net/fkbush/article/details/51200649