资源调度器是Yarn的核心组件之一,它是ResourceManager中的一个组件,负责整个集群资源的管理和分配。
ResourceManager要处理的各种事件:
ResourceManager本质上是一个事件处理器,处理来自外部的各种SchedulerEventType类型的事件,然后对Yarn上的资源做一些调整,事件有如下几种:
部分事件对应的动作如下:
NODE_ADDED/NODE_REMOVED:分别表示集群中增加了一个计算节点和删除了一个计算节点,需要对可分配资源总量进行相应的增加或者减少
APPLICATION_ADDED/APPLICATION_REMOVED:ResourceManager收到一个新的Application或者一个Application运行结束(可能成功可能失败),需要增加一个记录该Application信息的结构或者将结构删除
CONTAINER_EXPIRED:如果一个Container分配给某个ApplicationMaster之后再一定时间内没有使用,那么这个Container会回收再分配
NODE_UPDATE:接受NodeManager心跳汇报的信息,有可能是新的Container释放,此时该事件可能会触发资源调度器最核心的资源分配机制。
RMAppAttempt状态是干嘛用的?
每个Application会对应一个RMApp对象,保存该Application的各种信息。而每个RMApp可能会对应多个RMAppAttempt对象,取决与前一个RMAppAttempt对象是否成功,如果不成功则会启动另外一个,直到运行成功
Yarn的双层资源调度模型:
分配过程是异步的。资源调度器给ApplicationMaster分配资源之后会先放到一个缓冲区中,等待ApplicationMaster通过周期性的心跳来主动获取。
资源保证机制:
在分布式计算中,资源调度器需要选择合适的资源保证机制,当应用程序申请的资源暂时无法保证时:
1.优先为应用程序预留一个节点上的资源直到累计释放的空闲资源满足应用程序需求(称为“增量资源分配”)
2.暂时放弃当前资源直到出现一个节点剩余资源一次性满足应用程序需求(称为“一次性资源分配”)
这两种机制均存在优缺点,对于增量资源分配来说,资源预留会导致资源浪费,降低集群资源利用率;而一次性资源分配则会产生饿死现象,即应用程序可能永远等不到满足资源需求的节点出现,YARN采用了增量资源分配机制 ,尽管这种机制会造成浪费,但不会出现饿死现象;
Yarn的资源调度器
Yarn的资源调度器是可配置的,Yarn定义了一套接口规范(接口ResourceScheduler),用户可以按照自己的需求实现这个接口中的方法。Yarn自身自带了三种调度器,分别是:FIFO Scheduler、Capacity Scheduler(Yahoo!)和Fair Scheduler(Facebook)。
FIFO Scheduler:
最初Hadoop使用的就是FIFO这种非常简单的任务调度机制,所有的作业都被统一提交到一个队列中,优先给队列中的第一个任务分配资源,第一个任务资源满足后再给下一个分配,以此类推。
优点是简单可靠,也不需要任何配置。缺点也很明显,如果上一个作业一下子就把资源全部占光的话,那么下一个作业就需要等到上一个作业完成才能运行,这样不能充分利用硬件资源且不能满足多样化的需求。
所以FOFO Scheduler不适用于共享集群,共享集群更适合采用Capacity Scheduler或Fair Scheduler,这两个调度器都允许大任务和小任务在提交的同时获得一定的系统资源。
Capacity Scheduler:
设计思想是资源按比例分配给各个队列。这些队列是用户通过配置文件配置的。队列里的资源如果空闲的话,会被其他队列中的任务暂时占用(所以那个“队列最小容量”的配置不一定生效)。
每个队列都会设置一个最大资源占比,这样可以保证每个队列不用占用整个集群的资源。默认是不设置的,这样队列有可能使用100%的资源,当其他队列有应用程序提交时,再逐步归还。
每个用户也可以设定一定的资源上限,防止资源滥用。
队列内部是以FIFO方式调度的。正常情况下,Capacity Scheduler不会强行通过强行终止来强占容器。意思就是说,随着任务的增多,资源不够用时并且队列中的资源被其他队列给强占了,它只能等待其他队列释放资源。一般可以通过设置其他队列的最大容量来环节这种情况,这个就是需要权衡的地方。
Fair Scheduler:
设计思想是所有的应用分配公平的资源。公平是通过队列配置的权重(weight)来作为公平调度的依据,如果没有配置权重,那么所有队列的权重都为1,所有队列公平分配集群资源。
它也是以队列为单位划分资源,每个队列可以设置一定比例的资源最低保证和使用上限,同时每个用户也可设定一定的资源使用上限以防止资源滥用,当一个队列有资源剩余的时候可以共享给其他队列…和Capacity Scheduler基本一致
从图上可以看出,它不需要预留资源,因为调度器会在运行的作业之间动态平衡资源:第一个作业(用户A)启动时,由于是唯一运行的任务,所以它独占全部资源.当第二个作业(用户B)启动时,它会分配到一半资源.当然,第二个作业从启动到获得公平共享资源的时间会有滞后,因为必须等待第一个任务的容器用完并释放出资源,当第二个作业完成后,第一个作业会再次独占全部资源.
抢占功能,允许调度器Kill掉超过其应占份额资源队列的Containers(公平的定义),需要注意抢占会降低集群的执行效率,因为被终止的containers需要被重新执行。
默认情况下,Fair调度器只是对内存资源做公平的调度和分配,也可以配置成基于内存+Cpu。
总结:
如果业务逻辑比较简单或者刚接触Hadoop的时候建议使用FIFO调度器;如果需要控制部分应用的优先级同时又想要充分利用集群资源的情况下,建议使用Capacity调度器;如果想要多用户或者多队列公平的共享集群资源,那么就选用Fair调度器。
具体的源码层面细节的分析后面看完了再补充吧。