yarn最初是hadoop2.x用于改善mapReduce的,但是可以支持其他分布式应用。
yarn提供api来请求和使用集群的资源,但是用户不直接使用这些api,而是使用下图中 mr spark tez等程序会架构在yarn之上。
4.1 剖析 yarn应用的运行机制
2个常驻进程:
resourceManager: 总经理,管理整个集群的资源
nodeManager: 分厂经理,运行在各个节点上,启动和监控此节点的container
container :打工仔: 具体干活的人,有体力限制的(内存/cpu) 。一个容器可以是unix进程(默认), linux cgroup,取决于yarn的配置。
几个注意的点: 项目经理非常重要,而且也非常依赖这个项目(client提交的任务)
yarn本身不会为应用(mapreduce)的各个部分(client / master / 进程 )彼此间通信提供任何手段。
大多yarn应用使用某种形式的远程通信机制(hadoop的rpc)来向客户端返回应用的状态和结果,但这些通信机制属于应用本身。
4.1.1 资源请求
yarn有一个灵活的资源请求机制。当请求多个容器时,可以指定容器的cpu和内存,还可以指定对容器的本地要求。
本地化就不需要数据传输了,或者数据传输比较近,可以大大减小网络开销。
本地化是可以指定任意节点或者机架,或者是集群中的某个容器
如果本地化无法满足,就不分配资源,或者放松限制。比如本节点不能启动新的容器了,就尝试本机架的另外节点来启动,实在不行,就在本集群内启动。
yarn应用有两种资源请求方式:1 应用启动时,全部资源申请。 2 运行过程中,动态得去申请资源
spark就采用1,在集群中一开始就启动固定数量的执行器。 而mapReduce则开始启用map执行器,而后面再启动reduce执行器。
4.1.2 应用生命周期
书上用了一句这样的话来概况: 按照应用到用户运行的作业之间的映射关系对应用进行分类。初一看比较晦涩,不过他举了三个例子,就很好理解了:
mapReduce | 一个用户的作业就对应一个应用 | 最简单 |
spark | 作业的每个工作流或者每个用户对话(可能没有关系)来对应一个应用 | 比第一种高效,容器在作业之间可以重用,数据可以缓存共享 |
apace slider 和 impala | 多个用户共享一个长期运行应用,这个应用是协调者 | 高效,因为可以避免启动新的application master带来的开销 |
4.1.3 构建yarn的应用
编写一共yarn应用是很复杂的。
有现成的应用:
运行一个作业的有向无环图: spark tez
流计算:spark samza storm
apache slider: 使得在yarn上运行现有的分布式应用变成可能。它提供控制手段,可以修改应用运行所在的节点的数量,也可以暂停和恢复应用的运行。
apache twill:和slider类似,但是额外提供了一共简单的编程模型,用于开发yarn上的分布式应用。twill允许将集群进程定义为java runnable的扩展,然后在集群上的yarn容器中运行他们。twill同样为实时日志和命令消息提供支持。
如果上面的yarn应用都不符合你的要求,yarn项目自身一部分 distributed shell应用为如何写yarn应用做了一共示范。该应用演示了如何使用yarn客户端api来处理客户端或者application master 与yarn守护进程之间的通信。
4.2 yarn和mapReduce1对比
mr1中有两类守护进程控制着作业的执行过程: jobtracker(JT)和 n个taskTracker (TT)。
JT通过调度TT上运行的任务来协调所有运行在系统中的作业。
TT运行任务,同时将运行的进度报告发送给JT。
JT记录每项作业任务的整体进度情况。如果有失败的,就在另外一共TT上重现调度该任务。
JT的职责有:作业调度(将任务与TT匹配),任务进度监控(跟踪任务,重启失败或者延迟任务,记录任务流水)。存储已完成作业的作业历史,但是也可以运行一共作业历史服务器作为一个独立的守护进程来取代JT。
yarn会把这些职责分开,分别由resourceManager和 application master和 时间轴服务器来处理
yarn相对于mapReduce1的好处有4点:
可扩展性 | 当节点数达到4000,任务数4w时,mr1会遇到可扩展性瓶颈,因为JT必须同时管理作业和任务。 | yarn利用resourceManager和application master分离的特点,可以扩展到1W个节点,10W个任务。 |
可用性(HA) | 因为JT的内存中有大量快速变化的复杂状态,使得ha变得不可能。 | 由于yarn进行了拆分,使高可用的服务随之成为一个分而治之的问题:先为resourceManager提供高可用,再为master提供高可用。yarn的高可用将在7.2中讨论 |
利用率 | 每个taskTracker都分配有固定长度的slot,这些slot是静态的,分配的时候就固定好了是map slot和reduce slot,map的只能运行map作业,reduce slot只能运行reduce。 如果 | 节点管理器管理的是整个资源池,能够按需分配资源,而不是请求一个不可分割的,可能会太大(就会浪费)或者太小(任务失败)的slot |
多租户(叫多应用) | 不支持 | 面向mapReduce之外的应用也提供了支持(spark以及flink等),甚至可以运行多个版本的mr。 |
4.3 yarn中的调度
资源总是有限的,yarn调度器是根据配置好的策略来给为应用分配资源。
调度器是一个难题,没有一个最好的调度器。
yarn提供多种调度器来供我们选择
4.3.1 调度选择
yarn中有三种调度器: FIFO(先进先出), 容量调度器(capacity scheduler) ,公平调度器( fair scheduler)
FIFO | 把应用放在一个队列中,然后按照先进先出的顺序来依次执行应用。 | 简单易懂,不需要任何配置 | 不适合共享集群,大的应用会占用集群的所有资源 |
Capacity scheduler | 一个独立的专门作业保证小作业一被提交就马上运行 | 小作业得到额外照顾 | 集群利用率下降,大应用运行速度下降 |
Fair Scheduler | 不会预留资源,在运行作业时动态调整资源。先运行大应用,那么他会分配到所有资源,假如插进来一个小应用,那么会分一半资源来运行小作业。这样每个应用分配到相同的资源,就公平了 | 小作业能及时完成,集群的效率也有所提高 | 小作业启动到分配到资源正式运行有间隔,因为需要大作业释放资源并重新分配给他 |
4.3.2 容量调度器的配置
容量调度器允许多个组织共享一个hadoop集群,每个组织可以分配到集群资源的一部分。
每个组织被分配一个专门的队列,每个队列被配置为可以使用一定量的集群资源。
队列可以按层次划分,这样组织内的不同用户可以共享该组织所分配的资源。
在同一个队列内,采用FIFO策略调度。
弹性队列:如果某个队列的作业非常多,队列资源不够了,但是集群内仍然有空闲资源,那么容量调度器可能会将此资源分配给队列,这称为 弹性队列
如果某一个队列一开始资源够用,但是后面资源不够用了,他只能等待其他队列释放资源。同时也可以设置一个队列的最大容量(在配置文件里叫 maximum-capacity),以免它过多得侵占其他队列的资源。那这样就会牺牲队列弹性,因此需要在不断尝试和失败中找到一个合理的折中。
有一个配置文件叫 capacity-scheduler.xml,专门来配置整个容量调度器的配置的,这里不再展开。
队列放置:
将应用放置在哪个队列中,取决于应用本身。例如:在mapreduce中,可以通过设置 mapreduce.job.quenename来指定要用的队列。如果队列不存在,就会报错。如果不指定队列,就放在一个叫defaut的队列中。
4.3.3 公平调度器的配置
公平调度器旨在为所有job都公平分配资源。同一个队列中的应用是这样实现资源公平的:
多个队列其实也可以公平共享,如下图:
假如有2个用户A B ,平分集群的资源。
A先运行他的大作业1 ,结果开始占满了资源。
B 启动2作业,由于公平调度,他分了一半,过一会再启动作业3,3再从2那里抢到一半。
1 启用公平调度器
公平调度器由 yarn.resourcemanager.scheduler.clas来决定,默认是容量调度器,不过CDH是公平调度器。
讲此值设置为: org....FairScheduler
2 队列配置
通过一个叫 fair-scheduler.xml的文件来进行配置。
如果没有该配置文件,公平调度器的工作策略同之前描述的一样:每个应用放置在一个以用户名命名的队列中,队列是用户提交第一个应用时动态创建的。
分配文件不细说了,举了一个例子,两个队列,一个40,一个60,其实是按比例分配的,其效果和 2:3是一样的。
但是书本后面来了一句把我给整懵了:
这个值为1的权重是什么意思呢? 40:60:1 和 2:3:1的效果能一样吗???
根据我初步猜测:应该是作者上面那里写错了,40:60 和2:3的效果是不太一样的,因为有默认队列的1呢
每个队列还可以有不同的调度策略,默认是公平调度。不过可以设置,可以设置为FIFO,也可以设置为DRF
队列的调度策略可以被队列的scheduling policy元素指定的策略覆盖。
每个队列仍然需要配置最大 最小的资源数量,最大可运行的应用的数量。
最小资源量的作用: 不是一个硬性的限制,但是调度器常用它对资源分配进行优先排序。如果两个队列的资源都低于他们的公平共享额度,那么那个远低于最小资源数量的那个队列就优先获得分配。就是说,有2个队列,一个设置最小资源为10,一个设置为20。 假如同一时间,两个都只占了5,那么20那个会优先获取资源。
3 队列放置
公平调度器使用一个基于规则的系统来确定应用放在哪个队列。
1可以设置为:每条规则都会被依次尝试直到匹配成功。如果都没有匹配上就使用default队则,这样应用放进dev.eng队列中。
2可以设置为: 如果有确定的队列,就用确定的队列,否则会以用户名来创建队列。
3可以设置为:只有一个default队列,这样应用之间会公平共享资源,跟用户无关
4 可以通过把 yarn.scheduler.fair.user.as-default-queue设置为false,达到3的效果
5 可以把yarn.scheduler.fair.allow-undeclared-pools设置为false,用户就不能创建队列了
4 抢占
抢占,就是那些正在运行的资源,强行抢过来。
注意:抢占会降低集群的使用效率,因为那些被抢占的运行中的容器,会重新运行。
配置抢占:1 配置 yarn.scheduler.fair.preemption为true 2 配置两个抢占超时设置的一个。
最小共享抢占:minimumshare preemption timeout ,规定时间内为获取最小的共享资源,就发起抢占
公平共享抢占:fair share preemption timeout, 规定时间内获得的资源低于其公平共享份额的一半,也发起抢占。默认是 0.5,可以配置。
4.3.4 延迟调度
yarn调度器都试图以本地请求的方式启动应用。
应用在启动的时候,本地可能资源不足。不过,如果等待一会之后,很有可能就在本地分配到资源了。
容量调度器,公平调度器都支持延迟调度。
每个节点管理器定期(默认1秒)向资源管理器发送心跳请求。携带了正在运行的容器,新容器可用的资源等信息。
当启用延迟调度时,调度器不会简单使用它收到的第一个调度机会,而且等待设定的最大数目的调度机会发生,然后放松本地性限制并且接收下一个调度机会。
延迟调度,也是可以配置的。
4.3.5 主导资源公平性 DRF
DRF dominat resource fairness
有些应用用CPU多,有些应用用内存多,就观察这些应用的主导资源,并且作为对集群资源使用的一个读了。
比如一个集群有100CPU,100G内存,A用了2个CPU和3G内存,B用了6CPU和1内存。那么内存是A的主导资源,CPU是B的主导资源。在这里B申请的资源是A申请的两倍。所以B将分到一半的容器数???为啥呢?
默认是不用DRF的,因此在资源计算期间,只考虑内存,不考虑CPU。
4.4 延伸阅读
可参考 Apache hadoop yarn