Yarn支持配置不同的调度器,比较常用的就是Capacity和Fair,实际上Yarn一共有3中调度方式:
FIFO Scheduler 在 Hadoop 1.x 系列版本中,默认使用的调度器是 FIFO,它采用队列方式将每个任务按照时间先后顺序进行服务。比如排在最前面的任务需要若干 Map Task 和 Reduce Task,当发现有空闲的服务器节点时就分配给这个任务,直到任务执行完毕。
Capacity Scheduler 在 Hadoop 2.x/3.x 系列版本中,默认使用的调度器是 Capacity Scheduler(容量调度器),这是一种多用户、多队列的资源调度器。每个队列可以配置资源量,可限制每个用户、每个队列的并发运行作业量,也可限制每个作业使用的内存量;每个用户的作业有优先级,在单个队列中,作业按照先来先服务(实际上是先按照优先级,优先级相同的再按照作业提交时间)的原则进行调度。
容量资源调度器,支持多队列,但默认情况下只有 root.default 这一个队列。
当不同用户提交任务时,任务都会在这个队列里按照先进先出策略执行调度,很明显,单个队列会大大降低多用户的资源使用率。
因此,要使用容量资源调度,一定要配置多个队列,每个队列可配置一定比率的资源量(CPU、内存);同时为了防止同一个用户的任务独占队列的所有资源,调度器会对同一个用户提交的任务所占资源量进行限定。
Fair Scheduler Fair Scheduler(公平调度器)支持多用户、多分组管理,每个分组可以配置资源量,也可限制每个用户和每个分组中并发运行的作业数量;每个用户的作业有优先级,优先级越高分配的资源就越多。公平调度器的主要目标是实现 Yarn 上运行的任务能公平的分配到资源。
Fair Scheduler 将整个 Yarn 的可用资源划分成多个队列资源池,每个队列中可以配置最小和最大的可用资源(内存和 CPU)、最大可同时运行 Application 数量、权重,以及可以提交和管理 Application 的用户等。
Yarn也提供了通过参数的方式去切换调度器,但是这个切换在实现的时候,在源码层面是有瑕疵的,这个问题放到文章最后去描述,先看配置手法, 具体的配置方式,都是修改yarn-site.xml然后修改配置项,例如:
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> </property>
公平调度器的配置文件路径位于 HADOOP_CONF_DIR下 的 fair-scheduler.xml 文件中,这个路径可以通过配置 yarn-site.xml 文件,添加如下内容来实现:
<property> <name>yarn.scheduler.fair.allocation.file</name> <value>/etc/hadoop/conf/fair-scheduler.xml</value> </property>
若没有这个配置文件,调度器会在用户提交第一个应用时为其自动创建一个队列,队列的名字就是用户名,所有的任务都会被分配到 default 队列中。
接下来重点看看 fair-scheduler.xml 文件如何编写,此文件中定义队列的层次是通过嵌套元素实现的。所有的队列都是 root 队列的孩子,下面是一个定义好的公平调度策略:
<?xml version="1.0"?> <allocations> <!-- users max running apps --> <userMaxAppsDefault>10</userMaxAppsDefault> <queue name="root"> <aclSubmitApps> </aclSubmitApps> <aclAdministerApps> </aclAdministerApps> <queue name="default"> <minResources>12000mb,5vcores</minResources> <maxResources>100000mb,50vcores</maxResources> <maxRunningApps>22</maxRunningApps> <schedulingMode>fair</schedulingMode> <weight>1</weight> <aclSubmitApps>*</aclSubmitApps> </queue> <queue name="dev_group"> <minResources>115000mb,50vcores</minResources> <maxResources>500000mb,150vcores</maxResources> <maxRunningApps>181</maxRunningApps> <schedulingMode>fair</schedulingMode> <weight>5</weight> <aclSubmitApps> dev_group</aclSubmitApps> <aclAdministerApps>hadoop dev_group</aclAdministerApps> </queue> <queue name="test_group"> <minResources>23000mb,10vcores</minResources> <maxResources>300000mb,100vcores</maxResources> <maxRunningApps>22</maxRunningApps> <schedulingMode>fair</schedulingMode> <weight>4</weight> <aclSubmitApps> test_group</aclSubmitApps> <aclAdministerApps>hadoop test_group</aclAdministerApps> </queue> </queue> <queuePlacementPolicy> <rule name="user" create="false" /> <rule name="primaryGroup" create="false" /> <rule name="secondaryGroupExistingQueue" create="false" /> <rule name="default" queue="default" /> </queuePlacementPolicy> </allocations>
如果已经使用的是Yarn,或者FIFO,再切换至Capacity,是没有问题的,但是当已经使用了Capacity的时候,如果要再切换至Fair则有问题,这是因为对于Capacity来说,有一个参数:
yarn.resourcemanager.scheduler.monitor.enable
这个参数默认是false:
<property> <description>Enable a set of periodic monitors (specified in yarn.resourcemanager.scheduler.monitor.policies) that affect the scheduler.</description> <name>yarn.resourcemanager.scheduler.monitor.enable</name> <value>false</value> </property>
如果需要使用Capacity则需要把这个参数设置成true,这个参数是在Capacity场景下,对队列的监听,但是通过编码规则也能发现,光是从这个key,是无法感知到这个参数是只作用于Capacity的,因此如果切换至其他调度器而不把这个至设置成false。
则会出错,具体的错误看源码就能知道:
public void init(Configuration config, RMContext context, ResourceScheduler sched) { LOG.info("Preemption monitor:" + this.getClass().getCanonicalName()); assert null == scheduler : "Unexpected duplicate call to init"; if (!(sched instanceof CapacityScheduler)) { throw new YarnRuntimeException("Class " + sched.getClass().getCanonicalName() + " not instance of " + CapacityScheduler.class.getCanonicalName()); } rmContext = context; scheduler = (CapacityScheduler) sched; rc = scheduler.getResourceCalculator(); nlm = scheduler.getRMContext().getNodeLabelManager(); updateConfigIfNeeded(); }
这里hard code了CapacityScheduler的检查,所以在切换的时候,一定需要注意这个参数。
扫码手机观看或分享: