分类:
2010-09-09 13:22:47
从08年shao zheng给我们介绍fairscheduler到现在以及2年多了,从那次交流会上首次知道了fairscheduler,并在随后的集群上线中对fairscheduler进行了比较大的改造。比如第一版本的fairscheduler不支持队列之间的资源抢占,当时我们就加入了这个功能,另外第一版本的fairscheduler不支持组内作业之间的资源抢占,后来我们也加入进去了,等等一系列的修改,但是名字一直没有变,还叫FairScheduler,所以每次提到FairScheduler,总是觉得非常亲切。虽然后来还是有许多的问题,还是会在集群繁忙并且webui修改频繁的时候出现死锁,但是后来陆陆续续的改进也一直没有抛弃FairScheduler。各家公司的调度需求不同,同一家公司的不同集群调度需求也不同,但是伴随集群走的最久的,还是我们的FairScheduler,新发布的hadoop 0.21版本中,附带了fairScheduler的新版本,研究了一下发现,他也开始支持组间资源抢占,并且还提供了资源抢占的timeout思想,所以将facebook发布的新版本的fairscheduler使用手册整理了一下。回头再把源码的分析给整理整理,呵呵。
Fair scheduler是一种给job分配资源的调动方法,通过这种调度方式,可以使得所有job在一定时间内得到所有资源的一个平均共享。当只有一个job 在集群中运行时,这个job可以使用整个集群的资源,而此时当有其他的jobs提交到集群,那么在那个时刻空闲的集群槽位就可以被分配到新提交上来的 jobs,所以在一定时间内,每个job都得到了比较平均的cpu时间。hadoop默认的调度器采用的是一个job队列的方式来管理jobs,先提交到 队列中的job优先分配计算槽位,后提交的就后调度,这种调度方式可能发生的情况是,当有一个非常大的job,需要运行几十个小时,但是它优先于一个很小 的job提交到队列中,而实际上这个小job可能只需要几分钟就运行完成了,却需要等到这个大job运行完成后才能开始执行。跟hadoop默认的调度器 不一样,fairscheduler可以使得小job能够在很短的时间内完成,与此同时还不会出现大job因为分配不到槽位而永远无法运行完的情况。这种 方式还能够很好的实现在多个用户之间共享集群资源。平均共享的方式同样可以和作业优先级一起工作,作业的优先级可以被用来当做衡量每个job的重要程度来 决定分别给每个job分配多少槽位和计算资源。
FairScheduler将jobs用pools来管理,并将整个集群的资源按照pool来进 行划分。默认情况下,每一个user会对应一个单独的pool,所以每个user可以分配到集群的一份资源的划分。同时还可以根据用户所属的组或者其他懂 得jobconf中的属性来决定如何来对pool之间的资源进行划分。在每个一个pool内部,每一个job既可以根据fair share的值来进行调度,也可以使用first-in-first-out的方式来调度。
除了提供根据fair share进行调度的方式以外,FairScheduler还对每个pool提供了一个“可以确保该pool一定能满足的资源数”的一个值,这个值能够确 保说:即使在集群非常繁忙,资源非常紧张的情况下,至少能够确保给这个pool一定量的集群资源,也就是计算槽位,确保的槽位多少,就是这个值所定义的 量。当一个pool中运行了一些job的时候,这个pool中的所有job加起来“至少能够确保能够获得这个值定义的这么多的集群槽位”。但是当一个 pool中的所有job加起来也用不了这么多槽位的时候,多余的槽位仍然是可以被其他的pool使用的。这样可以打到资源合理利用,被浪费集群计算资源的 目的。
当 给一个pool确保的最小使用资源在一定时期内无法被满足的时候,那么scheduler将会采取资源“优先抢占”的策略来从别的pool中回收计算槽位 (对于每一个pool来说,是否在这种情况下采取这种策略是可选的)。pool是可以在这种情况下将别的pool中job的task进行kill来回收计 算槽位,以期望腾出足够的槽位来满足自己pool中job的计算槽位需求的。这种“优先抢占”的方式可以确保:对于一些比较重要的“生产作业”而言,不会 因为得不到槽位而一直无法运行完成的同时,还能让集群同时运行一些试验型和调研型的作业。不仅如此,pool还可以在其fair share在一段时间内(该时间间隔是可配置的,但必须确保该间隔要大于最小的采取优先抢占的timeout的时间)少于其确保值的一半的时候,开始采取 优先抢占的方式来获得计算槽位。当需要进行task kill来回收计算槽位时,FairScheduler会尝试从已经超出其应有的计算槽位的job中,选择最后开始被调度运行的task进行kill,以 将kill task所造成的资源浪费减少到最小。“优先抢占”的调度方式并不会造成job的失败,因为在hadoop中job是可以容忍有task失败的,失败的 task会在随后的调度中被重新调度到tasktrakcer上进行计算。
FairScheduler可以在pool层面来对每个pool中并行执行的job 数和每一个用户正在running的job数进行限制。这样可以保证当一个用户一下子提交了上百个作业的时候不会将集群的资源全部占用,也可以避免当并行 执行的作业过多,造成这么多的job所产生的中间结果过于庞大而将整个集群中可用的存储空间占满的情况。对pool的并行job数和用户的运行job数进 行了限制以后,对应随后的job将会进行等待,直到前面的job运行完成后,才可以被调度,并开始计算。在每个pool的等待队列中选择哪个job进行调 度的策略取决于作业的优先级以及该作业的提交时间。优先级越高,被选中的可能就越大,同样提交的时间越早,被选种的可能就越大。
最后,FairScheduler还能够对每个 pool中并行执行的作业task数进行限制。当job中有许多的map或者reduce,而每个map或者reduce task都需要对一些外部的服务进行访问(如数据库或者web服务器)时,不致于因为过多的task被并行的执行而导致这些服务由于过载而挂掉。
安装
如想要将fairscheduler用于自己的 hadoop集群中,需要将fairscheduler的jar文件放置到CLASSPATH中。最简单的方式为:将 hadoop-*-fairscheduler.jar的jar文件(通常包含在 HDOOP_HOME/build/contrib/fairscheduler中 )拷贝到 HADOOP_HOME/lib 中,或者在 HADOOP_CONF_DIR/hadoop-env.sh 中所指定的CLASSPATH中包含该jar文 件。然后,还需要在 HADOOP_CONF_DIR/mapred-site.xml 中,做如下配置:
完成,并启动集群后,可以通过在浏览器中访问 URL>/scheduler 的方式来确认是否已经成功启动。如果没问题,一个"job scheduler administration"的页面将会显示出来。该page中包含的内容在下文介绍。如果希望从源代码来编译fairscheduler,那么就需要 在HADOOP_HOME中运行ant package命令来编译,并在build/contrib/fair-scheduler/hadoop-*-fairscheduler.jar中找 到相应的jar文件。
FairScheduler包含有两个配置文件,算法相关的配置选项都需要在HADOOP_CONF_DIR/mapred-site.xml中进行配 置,还有另外一个独立的配置文件,默认情况下位置为:HADOOP_CONF_DIR/fair-scheduler.xml,该文件是用来配置 pool,最小槽位数,同时运行的job数限制,以及优先抢占时间间隔等配置。这个文件会被fairscheduler每隔一段时间就动态的加载一次,这 样管理员就可以在修改了配置后,不用重启jobtracker就能令配置生效。
最简单的情况下,管理员不需要对该文件做任何的配置就可以使用fairscheduler。
以下配置选项可以在mapred- site.xml中进行配置,用来对fairscheduler的调度算法进行配置:
基本选项
配置选项 | 描述 |
mapred.fairscheduler.preemption | boolean 选项,用来指定是否开启优先抢占功能,默认为: false. |
mapred.fairscheduler.pool | 定义 一个pool,如果对该选项进行了配置,那么mapred.fairscheduler.poolnameproperty的配置就会被乎略。 |
mapred.fairscheduler.poolnameproperty | 定义 哪一个jobconf的配置属性用来确定一个job所属的pool名称。是一个字符串值。默认情况下,用来确认一个job是属于哪个pool的配置选项 为:mapreduce.job.use.name(one pool for each user)。另外一个比较有用的配置为:group.name,用来位每一个Unix Group创建一个pool。 |
mapred.fairscheduler.allocation.file | 该选 项用来指定fairscheduler是要加载哪个文件来作为调度器特有的配置文件,默认为:HADOOOP_CONF_DIR/fair- scheduler.xml。该配置项的值必须是一个文件的绝对路径 |
高级配置
配置选项 | 描述 |
mapred.fairscheduler.sizebasedweight | 该选 项是一个boolean值,如果将该选项设置成true,那么当计算job的fair share时,会将该job的size(job的map和reduce数)作为计算fair share的依据。默认情况下该选项为false,也就是说默认job的fair share计算仅仅是由job的优先级来决定。当开启该选项后,fair share的变化和job size并非线性关系,但是会将job size计入用来计算fair share的因素。这样的机制能够使得大作业,需要运行时间长的作业,能得到更多的资源,而同时小作业也能够在一定合理的时间内完成。 |
mapred.fairscheduler.preemption.only.log | 该选 项是一个boolean值,默认为false。当开启时,fairscheduler会在内部调度时采用优先抢占的计算方法,但是并不会真正的kill task,而是当需要kill task的时候,仅仅向日志中写入一条记录,告诉管理员此时如果在真正的优先抢占调度模式下,会kill掉哪个task。这样提供了用户一种试运行的环 境,使得用户可以根据日志的记录情况来调整preemption的timeout是否设置的合理。日志的记录会在jobtracker的log中,如下列 格式: Should preempt 2 tasks for job_20090101337_0001: tasksDueToMinShare = 2, tasksDueToFairShare = 0 |
mapred.fairscheduler.update.interval | 该选 项用来设置fairscheduler更新各job的fair share的时间间隔。默认为500毫秒。通常情况下,这个时间间隔比较合适,如果集群规模超过500台甚至更多,可以考虑适当调大一点。视情况而定吧 |
mapred.fairscheduler.preemption.interval | I该 选项用来设置在资源抢占模式下,fairscheduler内部线程用来check是否需要抢占task槽位的时间间隔。默认为15秒(15000)。对 于这个配置,尽量不要设置的过小,不然很有可能会误杀很多的task,造成资源浪费。 |
mapred.fairscheduler.weightadjuster | 该选 项是fairscheduler的一个扩展点,用户可以自定义自己的class类,在类中自己定义算法来调整running job的比重,从而影响对job的fair share的计算,进而影响到对job的槽位分配。用户自定义的类需要集成WeightAdjuster接口。在fairscheduler的发行版中已 经附带了一个该接口的实现类,NewJobWeightBooster,该类的逻辑为:在job的运行前5分钟将job的比重加大,使得新提交上来的作业 在前5分钟内获得更多的槽位资源,以期望短小的作业能够尽快运行。若要使用该实现,可以将本配置选项设置成该类的全路径名,如 org.apache.hadoop.mapred.NewJobWeightBooster。这个类本身也提供了两个配置选项来配置对作业的比重计算的 调整因子:
|
mapred.fairscheduler.loadmanager | 该配 置选项也是fairscheduler的一个扩展点,loadmanager可以让用户自己定义需要给每个tasktracker分配多少个map和多少 个reduce task。该扩展点的实现类需要继承LoadManager接口。主要是可以让调度器根据每台tasktracker所剩余的内存和cpu使用率来决定分 配多少task到该tasktracker |
mapred.fairscheduler.taskselector | An extension point that lets you specify a class that determines which task from within a job to launch on a given tracker. This can be used to change either the locality policy (e.g. keep some jobs within a particular rack) or the speculative execution algorithm (select when to launch speculative tasks). The default implementation uses Hadoop's default algorithms from JobInProgress. 该选项也是一个fairscheduler的扩展点,可以让用户置顶自定义的实现类 来决定选择哪些task,分配到哪些tracker上。如此可以利用它来改变task分配原则(比如将某些task本配到同一个rack上等)以及预测执 行的行为算法。默认使用的时hadoop 的JobInProgress中的实现算法(随着版本不同会有不一样)。 |
Allocation File用来配置minimum share,并行job limit,每个pool的weight以及preemption timeout等。只有当某个用户或者某个pool需要设置的值跟默认的不一样时才需要进行额外配置。该配置文件默认的路径为 HADOOP_HOME/conf/fair- scheduler.xml。 该 配置中可以置顶如下配置项:
Pool and user elements only required if you are setting non-default values for the pool/user. That is, you do not need to declare all users and all pools in your config file before running the fair scheduler. If a user or pool is not listed in the config file, the default values for limits, preemption timeouts, etc will be used.
pool和user的配置项仅仅在需要对其设置非默认值时才需要。所以,并不需要明确的对所有的 pool或者user进行单独的配置。如果一个pool或者user没有在config文件中明确配置,那么就会用默认的值。
config文件的配置通常如以下格式:
该配置文件创建了一个pool名为 sample_pool,集群确保给该pool的最小map和reduce数为之5,该pool的最小share preemption的时间维度为300秒,这就意味着,如果在5分钟内该pool仍然没有使用槽位打到5个map 5个reduce,那么调度器就要从别的超出其自身min share的pool中抢占计算槽位来满足该pool的计算任务。该pool还设置了最大运行的map和reduce数,这就是说,当该pool内的所有 作业加起来使用了25个map,25个reduce后,就不会再给这个pool内的job分配槽位,即使在计算过程中该pool的fair share升高也不会。
上 述配置文件还对每个用户最多可以运行的job数做了限制,为3个。但是sample_user可以并行运行6个作业。最后,该配置文件还设置了抢占槽位的 时间超时为600秒。如果一个job所占用的槽位低于其fair share的一半超过10分钟,那么他将从其他pool中抢占计算槽位为己用。这里需要注意的是,要使这个配置选项生效,首先需要在mapred- site.xml中开启该功能。
其他没有在该配置文件中明确设置的pool,将不会被保证最小槽位数以及抢占槽位的timeout。并且,没有明确限制并行运行job上限的user或者 pool,默认都是可以运行无限多个作业的。
FairScheduler提供了两种实时的对作业运行情况进行调整管理的手段:
如下job运行信息能够在webui上查看到:
另外,还可以通过 URL>/scheduler?advanced 来查看一些作业运行期间的高级信息。可以看到