Yarn全名Yet Another Resource Negotiator
,即资源协调/管理者,在Hadoop2中引入。
Yarn,英文全名是 Yet Another Resource Negotiator,是由雅虎开发的第二代集群资源调度器。查看论文点这里。Yarn在大数据体系中的示意图如下:
而应用层在Application层之上,如Hive等。
和第一代不同,Yarn对各个角色进行了重新抽象。Yarn把JobTracker划分为了管理集群资源的ResourceManager(以下简称RM)和管理集群上运行任务的生命周期的AppMaster(以下简称AM)。此外,还有一个负责管理上报所在节点资源、响应处理AM的任务启停请求的角色NodeManager(以下简称NM)。
负责向Yarn提交App作业
每个Yarn集群一个RM(还可以设一个standBy节点做HA),负责整个集群的计算资源的管理和分配,RM主要由以下两部分组成
org.apache.hadoop.yarn.server.resourcemanager.RMAppManager
每个Yarn集群中有多个NM,每个NM有多个Container用于Container的启动和监测(每个NM上可能有多个Container)
注:根据Yarn配置的不同,Container可能是一个Unix进程或者一个Linux cgroup实例,在受限的资源范围内(如内存、CPU等)执行特定应用程序的代码。
NM主要功能如下:
协调、管理App的所有task。AM和task都运行在container中, container资源由RM调度分配, 由NM管理
AM 主要功能如下:
注意:Container不同于MRv1中的slot,它是一个动态资源划分单位,是根据应用程序的需求动态生成的。
YARN对内存资源和CPU资源采用了不同的资源隔离方案:
对于内存资源
为了能够更灵活的控制内存使用量,默认情况YARN采用了进程监控的方案控制内存使用,即每个NodeManager会启动一个额外监控线程监控每个container内存资源使用量,一旦发现超过指定资源,则会将该子进程杀死。
采用这种机制的另一个原因是Java中创建子进程采用了fork()+exec()的方案,子进程启动瞬间,它使用的内存量与父进程一致,从外面看来,一个进程使用内存量可能瞬间翻倍,然后又降下来,采用线程监控的方法可防止这种情况下导致swap操作以及误杀。而Cgroup对内存监控缺乏灵活,一旦发现任务使用内存资源超过阈值就会立刻杀死或抛出OOM异常。
对于CPU资源
采用了Cgroups进行资源隔离。
CGroups是一种将任务集及其所有未来子级集合/划分为具有特殊行为的分层组的机制。它是Linux内核功能,已合并到Linux 内核版本2.6.24中。 从YARN的角度来看,可使容器的CPU资源使用受到限制。
注意, YARN的资源分配过程是异步的,即RM将资源分配给一个application后,它不会立刻push给对应的AM,而是暂存到缓冲区,等待AM通过周期性的RPC函数主动来取。也就是说,资源分配采用pull-based模型,而不是push-based模型。
注意,需要注意的是,用户应用程序间各个组件的通信必须自己实现,Yarn没有提供通信工具。
在AM为tasks向RM申请Container时,该请求包括每个map task的数据本地化信息,特别是输入split所在的节点和机架(rack)信息。调度器会使用这些信息来进行调度决策。调度器会优先将task分配到所需数据所在节点执行,这就是所谓数据本地化策略,避免了远程访问数据的各种开销。
如果不能分配,那就会根据用户设置的RelaxLocality(本地化松弛,默认为true)来将task分配到本地化节点同机架的其他节点上。
比如申请处理HDFS数据的Container时,先考虑拥有该数据block副本的节点,如果没有再考虑这些副本所在节点同机架的其他节点,如果还是没有只能申请任意节点。
先说明下,每次提交Application的作业就是job,一般包括多个任务(task)。一个MapReduce job 包括多个map task和 reduce task。
我们这里引用《Hadoop权威指南》中一张十分经典的的MR Job运行在Yarn中的流程图:
下面说下详细步骤:
客户端进程启动job
向RM发出请求,获取一个代表此job的全局唯一appID
Client 检查job的输出说明,计算输入split分片数,并将job资源(包括job的jar、Configuration、分片信息等)写入到HDFS内,以便后续执行task时读取。这一步很关键。
Client向ResourceManager提交job。此提交请求中包含一个ApplicationSubmissionContext,他包括了RM为该App启动AM的所有信息:
该Job的AppMaster启动,分为两个步骤:
5a. RM首先为AppMaster在某个NM上分配、启动一个Container
5b. NM收到RM命令, 使用分配的Container来启动AppMaster
AM的主类MRAppMaster做一些Job的初始化工作,如监控作业进度等。
通过HDFS得到由客户端计算好的输入split,然后为每个输入split创建一个map task, 再根据mapreduce.job.reduces
创建指定数量的reducer task.
然后AM决定如何运行构成整个job的tasks。如果job很小, AM根据用户配置可以选择在本节点的JVM中运行该job, 这种job称作是uber job。
AM为tasks向RM申请Container
如果该job不是uber类型,那么AM机会向RM请求container来运行所有的map和reduce任务。 (注:每个任务对应一个container,且只能在该container上运行)。
该请求是一个由描述资源需求的ResourceRequest组成的列表,随后RM返回分配的资源描述Container。ResourceRequest的Protocol Buffers定义如下:
message ResourceRequestProto {
optional PriorityProto priority = 1; // 资源优先级
optional string resource_name = 2; // 资源名称(资源本地化信息,期望资源所在的node_host、rack名称等)
optional ResourceProto capability = 3; // 资源量(仅支持CPU和内存两种资源)
optional int32 num_containers = 4; // 满足以上条件的资源个数
optional bool relax_locality = 5 [default = true]; //是否支持本地性松弛
}
该请求包括每个map task的数据本地化信息,特别是输入split所在的节点和机架(rack)信息。调度器会使用这些信息来进行调度决策。调度器会优先将task分配到所需数据所在节点执行,这就是所谓数据本地化策略,避免了远程访问数据的各种开销。如果不能分配,那就会根据用户设置的RelaxLocality(本地化松弛,默认为true)来将task分配到本地化节点同机架的其他节点上。
请求还包括了task的内存需求, 默认情况下map和reduce任务的内存需求都是1024MB。 可以通过mapreduce.map.memory.mb
和mapreduce.reduce.memory.mb
配置。
注意,AM向RM发出自愿申请后不会立刻受到满足要求的Container资源,所以AM需要不断尝试与RM通信来拉取。RM可成功分配Container时,会返回Container描述信息给AM,每个这样的Container描述可用于启动一个任务。Container描述Protocol Buffers定义如下:
message ContainerProto {
optional ContainerIdProto id = 1; // Container id
optional NodeIdProto nodeId = 2; // Container所在NM id
optional string node_http_address = 3; // Container所在NM地址
optional ResourceProto resource = 4; // Container资源量
optional PriorityProto priority = 5; // Container优先级
optional hadoop.common.TokenProto container_token = 6; //Container用于安全认证的token
}
AM受到若干Container描述后,将他们分派给内部task。在Container资源成功分配给一个task后,分两个步骤来启动该task:
a. AM向NM发送启动指定container的RPC请求StartContainersRequest,其中封装了ContainerLaunchContext和Container信息,和一个任务对应;
b. NM通过收到的请求上下文中的信息带参数执行YarnChild
类的main方法。
资源本地化-去HDFS拉取task所需资源
在运行task之前,先去HDFS拉取task需要的所有文件到本地, 比如作业配置、JAR文件等所有来自HDFS的文件(具体需求在第九步提交的StartContainersRequest中),这一步称为数据资源本地化。
启动Map或者ReduceTask
注意:YarnChild运行在一个专用的JVM中, 但是YARN默认不支持JVM重用,因此每一个任务都是运行在一个新的JVM中。但是可以用uber job配置
应用程序运行完成后,AM向RM注销并关闭自己。
YARN中的task将其执行进度和状态上报给AM(使用TaskUmbilicalProtocol协议), AM每隔三秒将所有task上报的状态信息合并为该Job的整体状态视图。
如果开启了verbose,Client每秒(默认值为1秒,可以通过
mapreduce.client.progressmonitor.pollinterval
设置)向AM请求查询任务实时的执行情况,方便用户查看。
在YARN中, 可以通过UI看到所有的App运行情况。具体来说,RM的WebUI 展示运行中的App以及对应的AM。AM展示管理的tasks进度等细节信息。
在Job生命周期内,Client可从AM查询Job进度, 还会每5秒(未开启verbose时的默认值,可通过mapreduce.client.completion.pollinterval
设置)检查是否完成。
Job完成之后, AM和container会清理自己的工作状态, OutputCommiter的作业清理方法也会被调用。Job的信息会被Job历史服务器存储以备之后用户核查。
Yarn的失败包括task失败、AM失败、NM失败甚至是RM失败,下面详细介绍下这几种情况。
task程序运行时异常和JVM进程突然退出会上报到AM,此次task尝试失败。
还有一种情况是task挂起。task运行过程中会定期调用TaskUmbilicalProtocol
协议中ping方法联系AM,如果程序挂起导致AM一直收不到ping(通过mapreduce.task.timeout
设置),就会判定该task超时,AM将该次task尝试标记为失败。如果将上述配置设为0 ,代表task不会被标记为失败,导致其资源无法释放,可能会出大问题,不推荐。
task尝试失败后,AM尝试重新执行该任务,同时要避免在失败节点上重跑。重试次数的配置如下:
map task:mapreduce.map.maxattempts
,
reduce task:mapreduce.reduce.maxattempts
。
task尝试失败次数超过这个阈值,就会认为这个task失败,不再进行重试。
最后说下怎么判定整个job的失败。如果一个MapReduce job中超过mapreduce.map.failures.maxpercent
的map task 或者mapreduce.reduce.failures.maxpercent
reduce task运行失败,就判定该job失败。
AM会定时向RM发送心跳。如果AM故障(如硬件故障或网络错误等),RM可感知到并在新的container中运行一个新的AM实例。在默认情况下,只要AM运行失败一次,然后重试一次又失败就被认为是AM失败了不再重试。可以通过mapreduce.am.max-attempts
来设置该值。
Yarn有一个全局参数yarn.resourcemanager.am.max-attempts
,默认值为2,可以控制所在yarn上运行的AM的重试次数,也就是说上面讲的每个任务的重试次数不能超过这个全局参数。
MapReduce的AM恢复后,可以通过job历史来恢复故障App所运行tasks的状态,使其不需要重跑。可以通过设置yarn.app.mapreduce.am.job.recovery.enable
为false,关闭此功能。
Client会向AM轮询job进度报告,当AM运行失败时,客户端需要重新定位新的AM实例。在job初始化的时候,client就通过请求RM得到并缓存了AM地址,这样做的好处是Client每次向AM查询时变得更快。在AM运行失败时,Client会因为请求超时而重新向RM请求最新的AM地址,这个过程对用户完全透明。
NM也会定期向RM发送心跳。如果RM在10分钟内(默认值,可通过yarn.resourcemanager.nm.liveness-monitor.expiry-interval-ms
设置)发现未收到任何来自某个NM节点的心跳,RM会将该节点从节点池中移除并通知该节点。
在该失败的NM上运行的所有App或AM就按照上文所述机制恢复。
注意:由于map task输出结果驻留在失败NM上的原因,所以在这些节点上运行成功的map task(所属job还未完成)还是需要重新调度运行,以免造成NM节点被踢掉后reduce任务无法拉取所需数据
最后要注意的是,如果累积的App运行失败次数过多,那么所在NM节点可能会被AM放入自己管理的黑名单(不管NM是否失败过)。对于MapReduce任务,默认累积超过3个task失败就会将此NM拉黑,任务会尽量分配到其他节点。该阈值的配置是mapreduce.job.maxtaskfailures.per.tracker
。
注意:当前版本hadoop中,黑名单由应用程序的AM管理,对RM透明,也就是说就算老的App把某个NM节点拉黑,但是新的App的任务依然有可能分配到这些故障节点
RM作为Yarn的大脑,如果失败后果十分严重,如果没有配置StandBy RM的话会存在单点故障风险,会导致所有运行的job全部失败且无法恢复。可以用共享存储解决这个问题,源码中该接口为RMStateStore
,利用ZooKeeper(ZKRMStateStore)或HDFS(FileSystemRMStateStore)做了RM HA那么active RM挂掉的情况下会自动切换到standBy RM,Client无明显感知。
RM HA时可以把运行中的App(不包括AM管理的任务信息)信息存储在高可用的Zookeeper或HDFS中备份,以备failover时备节点恢复关键状态信息。NM的信息未保存,因为是心跳调度机制,当备RM节点恢复服务收到NM心跳时可以快速重构NM状态信息。
RM备节点接管后,会从上面的状态存储区中读取信息进行恢复,为所有App重启AM。
上述RM HA过程是由FailoverController
自动处理,他在默认情况下运行在RM内,使用zookeeper的leader选举机制来确保同一时刻只有一个主RM。
首先,简单回顾一下Hadoop 1.x中的JVM重用功能:用户可以通过更改配置,来指定TaskTracker在同一个JVM里面最多可以累积执行的Task的数量(默认是1)。这样的好处是减少JVM启动、退出的次数,从而达到提高任务执行效率的目的。 配置的方法也很简单:通过设置mapred-site.xml里面参数mapred.job.reuse.jvm.num.tasks的值。该值默认是1,意味着TaskTracker会为每一个Map任务或Reduce任务都启动一个JVM,当任务执行完后再退出该JVM。依次类推,如果该值设置为3,TaskTracker则会在同一个JVM里面最多依次执行3个Task,然后才会退出该JVM。
在 Yarn(Hadoop MapReduce v2)里面,不再有参数mapred.job.reuse.jvm.num.tasks,但它也有类似JVM Reuse的功能——uber。据Arun的说法,启用该功能能够让一些任务的执行效率提高2到3倍(“we’ve observed 2x-3x speedup for some jobs”)。不过,由于Yarn的结构已经大不同于MapReduce v1中JobTracker/TaskTracker的结构,因此uber的原理和配置都和之前的JVM重用机制大不相同。
Yarn的默认配置会禁用uber组件,即不允许JVM重用。我们先看看在这种情况下,Yarn是如何执行一个MapReduce job的。首先,Resource Manager里的Application Manager会为每一个application(比如一个用户提交的MapReduce Job)在NodeManager里面申请一个container,然后在该container里面启动一个Application Master。container在Yarn中是分配资源的容器(内存、cpu、硬盘等),它启动时便会相应启动一个JVM。此时,Application Master便陆续为application包含的每一个task(一个Map task或Reduce task)向Resource Manager申请一个container。等每得到一个container后,便要求该container所属的NodeManager将此container启动,然后就在这个container里面执行相应的task。等这个task执行完后,这个container便会被NodeManager收回,而container所拥有的JVM也相应地被退出。在这种情况下,可以看出每一个JVM仅会执行一Task, JVM并未被重用。
用户可以通过启用uber组件来允许JVM重用——即在同一个container里面依次执行多个task。在yarn-site.xml文件中,改变一下几个参数的配置即可启用uber的方法:
参数 | 默认值 | 描述 |
---|---|---|
mapreduce.job.ubertask.enable | (false) | 是否启用user功能。如果启用了该功能,则会将一个“小的application”的所有子task在同一个JVM里面执行,达到JVM重用的目的。这个JVM便是负责该application的ApplicationMaster所用的JVM(运行在其container里)。那具体什么样的application算是“小的application"呢?下面几个参数便是用来定义何谓一个“小的application" |
mapreduce.job.ubertask.maxmaps | 9 | map任务数的阀值,如果一个application包含的map数小于该值的定义,那么该application就会被认为是一个小的application |
mapreduce.job.ubertask.maxreduces | 1 | reduce任务数的阀值,如果一个application包含的reduce数小于该值的定义,那么该application就会被认为是一个小的application。不过目前Yarn不支持该值大于1的情况“CURRENTLY THE CODE CANNOT SUPPORT MORE THAN ONE REDUCE” |
mapreduce.job.ubertask.maxbytes | application的输入大小的阀值。默认为dfs.block.size的值。当实际的输入大小部超过该值的设定,便会认为该application为一个小的application。 |
最后,我们来看当uber功能被启用的时候,Yarn是如何执行一个application的:
随着大量应用基于Yarn申请资源运行,所以资源调度是重中之重,我们需要根据实际情况选择调度策略,目前有三类调度器,如下图
默认情况下,每个NM以1秒的时间间隔周期性的发送心跳给RM,心跳信息携带了NM的运行中container以及其他可用资源信息。所以,每次心跳就是一次潜在的调度资源运行container的机会。
在繁忙集群中,如果一个应用请求特定节点资源,则可能有很多其他container已经在该节点上运行无空闲资源。此时最简单的方式就是放松本地性而在同机架的其他空闲节点上。
然而,有统计在实践中如果再等很短一段时间(一般不超过几秒)就很有机会能分配请求的本地性节点的资源从而提高集群整体效率。这个延迟调度的过程就称为延时调度机制。
开启延迟调度后,调度器就可在放松本地性限制前先等待最大调度机会次数,以此尽可能使用本地性调度。
将yarn.scheduler.capacity.node-locality-delay
设为正数,默认为一个机架上的节点数即40。经典做法是将其设为集群中的NM节点数。
参见Fair Scheduler章节配置小结的yarn.scheduler.fair.locality.threshold.node
和yarn.scheduler.fair.locality.threshold.rack
。
全称Dominant Resource Fairness
。
只有一种资源如内存时,资源分配的公平性很好界定,但要用多个维度时就不好衡量,因为不同维度资源量无法统一量化。
比如一个集群100个CPU和10TB内存。应用A请求(2CPU,300GB内存),占整个集群的百分比为(2%,3%),则百分比更大的内存为占优资源;B请求(6CPU,100GB内存),占整个集群的百分比为(6%,1%),占优资源为CPU。所以公平共享条件下,B应该分配2倍于A的资源(因为6%=3% * 2
)
Capacity调度器的默认yarn.scheduler.capacity.resource-calculator
为DefaultResourceCalculator
就是只计算内存,而可选DominantResourceCalculator
来使用DRF机制计算多个维度的资源如内存、CPU等。
可设定defaultQueueSchedulingPolicyi
或schedulingPolicy
为drf。
使用场景
适用于大量业务团队共享的集群。
原理
一个集群配置多个队列且队列内可进一步划分队列形成队列树形结构,每个队列被配置使用一定量的集群资源,队列内部使用FIFO方式调度。
多个业务团队使用一个或多个队列,同一个团队的不同用户就可以共享分配的队列资源。
队列弹性调度
单个作业使用的资源不会超过其所在队列资源容量。但如果作业没有足够资源且集群其他队列有空闲资源可用时,容量调度器可能触发队列弹性机制来分配空闲资源给该作业,此时可能该队列使用资源超过设置的队列阈值。
这样能保证队列资源弹性可用,作业运行时间可预测,可阻止人为分配队列造成的浪费,提高集群整体资源利用率。
抢占
默认容量调度器不会强行终止来抢占container资源(除非设置work-preserving
抢占,此时RM会要求应用返还多占用的资源来平衡队列容量),也就是说资源不够时只能等待其他队列释放容器资源,此时可设置队列最大容量。
特点
小作业提交到专门的队列快速开始,不受别的队列的大作业影响。但降低了集群整体资源利用率,大作业执行时间较FIFO更长。其他特点:
队列内的FIFO调度可设置优先级,整数值越高则应用优先级越大。
可使得调度器从那些使用的资源量超过了配置的保证容量的队列处抢占container资源。
CapacityScheduler支持ReservationSystem
,它允许用户提前保留资源。
应用程序可以在提交时通过指定reserveId
来在运行时请求所保留的资源。
请参考:
org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler
,表示RM使用容量调度器。yarn.scheduler.capacity.
基本配置格式,queue-path
表示.
分隔的队列层次路径,sub-property
表示属性名。
yarn.scheduler.capacity.root.chengc.capacity
某个队列基础容量百分比
yarn.scheduler.capacity.root.chengc.maximum-capacity
某个队列最大容量百分比,可使得队列不过多占用集群资源。
设置太小可能牺牲集群队列弹性,设置太大会使得队列占用过多资源导致其他队列无资源可用,需要反复尝试调整。
yarn.scheduler.capacity.root.chengc.user-limit-factor
允许单个用户最多可获取的队列资源的倍数。
默认值为1,为浮点数,可确保单个用户永远不会占用超过队列配置的资源无论集群是否空闲。
注意:
chengc
队列的yarn.scheduler.capacity.root.chengc.maximum-capacity
),就算设置超过也按队列最大资源量获取资源上限,只能超过yarn.scheduler.capacity.root.chengc.capacity
假设有以下队列:
root
|--prod
|--dev
|--eng
|--science
则capacity-scheduler.xml
文件配置示例如下:
<configuration>
<property>
<name>yarn.scheduler.capacity.root.queuesname>
<value>prod,devvalue>
property>
<property>
<name>yarn.scheduler.capacity.root.dev.queuesname>
<value>eng,sciencevalue>
property>
<property>
<name>yarn.scheduler.capacity.r oot.prod.capacityname>
<value>40value>
property>
<property>
<name>yarn.scheduler.capacity.root.dev.capacityname>
<value>60value>
property>
<property>
<name>yarn.scheduler.capacity.root.dev.maximum-capacityname>
<value>75value>
property>
<property>
<name>yarn.scheduler.capacity.root.dev.eng.capacityname>
<value>50value>
property>
<property>
<name>yarn.scheduler.capacity.root.dev.science.capacityname>
<value>50value>
property>
configuration>
该配置要点如下:
更多配置如单个用户、单个应用分配最大资源、并发运行应用数、队列ACL认证等内容请参考:
使用容量调度器时,要指定作业运行队列,名字请使用层级队列末尾名字,比如要使用root.dev.eng
这个队列必须时而用eng
而不能使用全名。不指定队列名时浆放入default队列。
使用场景
追求集群整体资源利用率时。
原理
公平调度器为所有应用公平分配资源,公平性体现在队列间和队列中:
特点
集群整体资源利用率高,大作业能加快速度完成,小作业也能及时完成。
不需要预留资源,因为调度器会在所有运行的作业之间动态平衡分配资源。
具体来说,首个运行的大作业可获得集群所有资源;第二个小作业启动时可等待第一个大作业使用的部分容器用完释放后分配集群一半资源,保证了公平性。且第二个小作业结束后释放了资源,大作业又可以再次使用全部集群资源了。
由allocations文件内的queuePlacementPolicy
定义rule
元素列表依次匹配来决定提交的应用放在哪个queue中。
背景
在一个繁忙的、空闲资源很少或没有的集群中,新提交一个job到空队列时不会立刻启动,而必须等待其他队列job释放资源且调度器分配足够资源给本队列后才行。
所以为了让job从提交到启动时间可预测,fair调取器支持抢占策略。
原理
抢占机制规定调度器可以kill那些超过公平共享份额的队列所运行的container,这样就能将释放出的资源分配给那些资源低于公平共享份额的队列。
抢占时机:
minSharePreemptionTimeout
(默认最顶层defaultMinSharePreemptionTimeout
)还未收到至少达到minResource的资源,则调度器可能会抢占其他队列运行的container。fairSharePreemptionTimeout
(默认最顶层defaultFairSharePreemptionTimeout
)还未收到至少达到fairSharePreemptionThreshold * fairShare
(这里的阈值默认也是顶层的defaultFairSharePreemptionThreshold
)的资源的资源,则调度器可能会抢占其他队列运行的container。缺点
因为container需要先杀死再重启,所以抢占机制会降低集群整体效率。
配置
参考后续3.4.2配置章节preemption相关内容。注意默认没有抢占超时时间,所以想启用抢占还必须设定minSharePreemptionTimeout
和fairSharePreemptionTimeout
中至少一个。
请参考:
yarn.resourcemanager.scheduler.class
请设置为org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
,表示RM使用公平调度器分配资源。
yarn.scheduler.fair.allocation.file
队列配置文件名称,默认为fair-scheduler.xml
。该文件主要用于描述各个队列的属性,比如资源量、权重等
如果没有该文件,则每个应用提交时会被放置到一个以用户命名的队列中,这些队列是提交该应用的用户首次提交应用时动态创建的。
yarn.scheduler.fair.user-as-default-queue
默认true
当应用程序提交时未指定队列名时,是否使用用户名作为默认队列名。如果设置为false或者未设置时所有未知队列的应用程序将被提交到default
队列。
yarn.scheduler.fair.preemption
默认false
是否启用抢占机制
yarn.scheduler.fair.preemption.cluster-utilization-threshold
开启了抢占后生效,整体集群资源利用率阈值
yarn.scheduler.fair.sizebasedweight
默认false
默认在队列内部分配资源时采用公平轮询的方法,将资源分配给各个应用,不考虑资源大小。
设置为true时,应用程序将以1的自然对数加上应用程序的总请求内存除以2的自然对数来加权。即按照应用程序资源请求量来分配资源,即需求资源数量越多,权重越高。
yarn.scheduler.assignmultiple
默认fale
是否允许一次心跳多次分配资源。
yarn.scheduler.fair.dynamic.max.assign
默认true
开启assignmultiple
时,是否开启动态决定一次心跳调度时分配资源量。开启后,该心跳NM节点的约一半未分配资源会在单次心跳中被分配给container们。
yarn.scheduler.fair.max.assign
默认-1代表不限制
开启assignmultiple
且禁用dynamic.max.assign
时生效,用来指定一次心跳调度中分配的最大container数目。
yarn.scheduler.fair.locality.threshold.node
默认-1.0,表示不跳过任何调度机会。该值表示为介于0到1之间的浮点数。
对于在特定NM节点上请求容器的应用程序,自上一次容器分配以来在接受另一个NM节点上的放置之前要等待的调度机会次数阈值。
当按照分配策略,可将一个节点上的资源分配给某个应用程序时,如果该节点不是应用程序期望的节点,可选择跳过该分配机会暂时将资源分配给其他应用程序,
直到出现满足该应用程序需的节点资源出现。通常而言,一次心跳代表一次调度机会,而该参数则表示跳过调度机会占节点总数的比例。
yarn.scheduler.fair.locality.threshold.rack
默认-1.0,表示不跳过任何调度机会。该值表示为介于0到1之间的浮点数。
当应用程序请求某个特定机架上的资源时,它可接受的可跳过最大资源调度机会次数阈值。
yarn.scheduler.fair.allow-undeclared-pools
默认true,即可在应用提交时创建新队列(由于应用提交时指定的队列或者取决于user-as-default-queue
属性)。
如果为false,只要应用提交的队列未提前指定,则总是会提交到default
队列中。
如果allocations配置文件中定义了队列规则,则该属性将会被忽略。
yarn.scheduler.fair.update-interval-ms
默认500ms
锁定调度器以重新计算公平份额、重新计算资源需求以及检查是否触发抢占的时间间隔。
minResources
一个queue的最小资源量,设置格式为X mb, Y vcores
,队列资源小于公平份额的会在同parent队列级别被优先分配资源;如果多个队列同时不满足minResources,则资源优先分配给相对资源使用量/最小共享资源
的比例最小的队列。minResources也被用在抢占(preemption)机制。
对于不同的调度策略,minResources含义不同:
maxResources
一个queue最多可以使用的资源量,可写为X mb, Y vcores
或X% memory, Y% cpu
(表示占整个集群资源百分比)。
如果队列申请的container资源加上该队列已使用的资源超过了maxResources,则不会分配该container。
maxChildResources
一个ad hoc子queue最多可以使用的资源量,可写为X mb, Y vcores
或X% memory, Y% cpu
(表示占整个集群资源百分比)。
如果队列申请的container资源加上该ad hoc子queue已使用的资源超过了maxResources,则不会分配该container。
maxRunningApps
限制一个队列同时运行的应用程序数。
maxAMShare
浮点数,默认0.5f,可填-0.1f禁用此检查。
限制一个队列的公平份额中可用来运行AM的部分,只对叶子队列生效。比如0.9f会允许叶子队列使用内存和CPU资源的90%的。
weight
默认为1。
队列间的分配资源权重值,越大分配的越多,比如设为2的队列资源是默认的队列资源的大约2倍。
schedulingPolicy
默认fair
本队列采用的调度模式,内嵌可选的有fifo、fair、drf,也可是继承自org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.SchedulingPolicy
的类。
aclSubmitApps
可向队列中提交应用程序的用户或用户组列表,默认情况下为“*”,表示任何用户均可以向该队列提交应用程序。
需要注意的是,该属性具有继承性,即子队列的列表会继承父队列的列表。配置该属性时,用户之间或用户组之间用``分割,
用户和用户组之间用空格分割,比如user1, user2 group1,group2
。
aclAdministerApps
该队列的管理员账户/管理员组列表。
一个队列的管理员可管理该队列中的资源和应用程序,比如可杀死任意应用程序。
minSharePreemptionTimeout
默认Long.MAX_VALUE,即表示从不抢占资源。单位为秒。
如果一个队列在该段时间内使用的资源量低于最小共享资源量,则开始抢占其他队列的资源。
如果不设置,就从父队列继承该值。
fairSharePreemptionTimeout
默认Long.MAX_VALUE,即表示从不抢占资源。单位为秒。
如果一个队列在该段时间内使用的资源量低于fair共享资源量,则开始抢占其他队列的资源。
如果不设置,就从父队列继承该值。
fairSharePreemptionThreshold
默认0.5f,该队列的公平共享资源抢占阈值
如果队列等到了fairSharePreemptionTimeout
都还没有收到fairSharePreemptionThreshold * fairShare
的资源,就允许从其他队列抢占container以获取资源。
如果不设置,就从父队列继承该值。
allowPreemptionFrom
默认true。
决定调度器是否能从该队列抢占资源。
如果设定为false,则会递归到所有子队列。
reservation
向ReservationSystem表明该队列的资源可对用户提供保留。
该配置仅适用于叶子队列。 如果未配置此属性,则叶子队列不能提供保留。
以下设置在allocations
下一级。
User
单个用户的设置,目前可为单个用户添加maxRunningApps
属性限制其最多同时运行的应用程序数量。
userMaxAppsDefault
没配置maxRunningApps的默认用户同时运行的应用程序数量。
defaultFairSharePreemptionTimeout
队列的fairSharePreemptionTimeout属性的默认值。
defaultMinSharePreemptionTimeout
队列的minSharePreemptionTimeout属性的默认值。
defaultFairSharePreemptionThreshold
队列的fairSharePreemptionThreshold属性的默认值。
queueMaxAppsDefault
队列的maxRunningApps属性的默认值。
queueMaxResourcesDefault
队列的maxResources属性的默认值。
queueMaxAMShareDefault
队列的maxAMShare属性的默认值。
defaultQueueSchedulingPolicy
队列的schedulingPolicy属性的默认值。
reservation-agent
默认值org.apache.hadoop.yarn.server.resourcemanager.reservation.planning.AlignedPlannerWithGreedy
。
该项应设定实现自ReservationAgent
的类,用来放置用户的驻留请求到Plan
中。
reservation-policy
默认值org.apache.hadoop.yarn.server.resourcemanager.reservation.CapacityOverTimePolicy
。
该项应设定实现自SharingPolicy
的类,用来验证新的驻留请求是否违反任何规则。
reservation-planner
默认值org.apache.hadoop.yarn.server.resourcemanager.reservation.planning.SimpleCapacityReplanner
。
该项应设定实现自Planner
的类,会在Plan
容量跌落(由于维持调度或节点故障)到低于用户保留资源时调用。此时它会扫描Plan
并按接受的逆序(LIFO)贪心地删除保留,直到保留的资源在Plan
容量之内。
queuePlacementPolicy
包含若干rule
元素用来告知调度器把新提交的应用放入哪个队列,其中rule的命中以列表中配置先后顺序为准。
rule元素的create
参数的含义是决定是否本规则可创建新队列,默认为true
;如果设置为false,且该规则命中后试图把应用放入没在allocations
问价那种配置的队列,则会跳过本rule继续匹配队列中的下一条rule。注意,最后一条规则必须配置不能再跳过。
未配置queuePlacementPolicy
时,默认就是如下配置,此时就是先按用户指定的队列提交,若无指定或不存在就使用用户名队列:
<queuePlacementPolicy>
<rule name="specified"/>
<rule name="user"/>
queuePlacementPolicy>
合法的rule值如下:
.q1
或q1.
”将被拒绝。_dot_
,即用户first.last
的队列名称为first_dot_last
。primary Unix group
名称的队列中。组名称中的句点将替换为_dot_
。secondary Unix group
名称的队列中。组名中的句点将被替换为_dot_
。user
规则,区别在于nestedUserQueue
规则中,用户队列可以在任何父队列下创建,而user
规则仅在root
队列下创建用户队列。请注意,只有在嵌套规则返回父队列时才应用nestedUserQueue规则。可以通过将队列的type
属性设置为parent
或通过在该队列下配置至少一个叶子队列来配置父队列。queue
属性指定的队列中。如果未指定queue
属性,则将应用程序放置在root.default
队列中。同样假设有以下队列:
root
|--prod
|--dev
|--eng
|--science
则可配置如下
<allocations>
<defaultQueueSchedulingPolicy>fairdefaultQueueSchedulingPolicy>
<queue name="prod">
<weight>40weight>
<schedulingPolicy>fifoschedulingPolicy>
queue>
<queue name="dev">
<weight>60weight>
<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>
该配置要点如下:
defaultQueueSchedulingPolicy
可以定义每个队列内部的默认调度策略。如果没有设定,则采用fair公平调度器。还可选fifo和drf(Dominant Resource Fairness)schedulingPolicy
。primary Unix group
名称的队列中且不能创建不存在队列;queue
属性指定的队列即dev.eng
中。例子来自于FairScheduler:
<allocations>
<queue name="sample_queue">
<minResources>10000 mb,0vcoresminResources>
<maxResources>90000 mb,0vcoresmaxResources>
<maxRunningApps>50maxRunningApps>
<maxAMShare>0.1maxAMShare>
<weight>2.0weight>
<schedulingPolicy>fairschedulingPolicy>
<queue name="sample_sub_queue">
<aclSubmitApps>charlieaclSubmitApps>
<minResources>5000 mb,0vcoresminResources>
queue>
<queue name="sample_reservable_queue">
<reservation>reservation>
queue>
queue>
<queueMaxAMShareDefault>0.5queueMaxAMShareDefault>
<queueMaxResourcesDefault>40000 mb,0vcoresqueueMaxResourcesDefault>
<queue name="secondary_group_queue" type="parent">
<weight>3.0weight>
<maxChildResources>4096 mb,4vcoresmaxChildResources>
queue>
<user name="sample_user">
<maxRunningApps>30maxRunningApps>
user>
<userMaxAppsDefault>5userMaxAppsDefault>
<queuePlacementPolicy>
<rule name="specified" />
<rule name="primaryGroup" create="false" />
<rule name="nestedUserQueue">
<rule name="secondaryGroupExistingQueue" create="false" />
rule>
<rule name="default" queue="sample_queue"/>
queuePlacementPolicy>
allocations>
可参考:
yarn application -status application_id
yarn application -kill application_id
见Hadoop-Yarn-调优
见Hadoop-Yarn-常见问题