【原理介绍】
在hadoop官方文档中,描述了容量调度支持按任务的优先级来调度。
具体来说就是:客户端向yarn提交任务时,可以指定任务的优先级。任务的优先级是一个正整数,值越大意味着任务的优先级越高;在容量调度的队列中,对任务按优先级进行排序,优先级越高的任务,会优先进行资源的分配。
不同类型的任务在提交时,通过不同参数指定优先级,但基本上大同小异,例如:
MapReduce | "-Dmapreduce.job.priority=xx" |
Flink | "-yD yarn.applicaiton.priority=xx" |
Spark | "spark.yarn.priority=xx" |
注意:spark的参数在3.0版本后才引入使用
既然任务提交时,优先级可以通过参数指定,那么如果没有指定优先级,是否会有对应的默认值呢?答案是肯定的。
在yarn中,任务的优先级有两个维度配置:一个是全局最大优先级,一个是队列默认优先级。
队列中任务的默认优先级在配置文件capacity.scheduler.xml中进行配置,例如:
<property>
<name>yarn.scheduler.capacity.root.hncscwc.default-application-priority</name>
<value>80</value>
</property>
该配置指定hncscwc队列中任务的默认优先级为80。
需要注意的是:队列中的默认优先级仅作用于未设置优先级的任务,即如果提交任务时没有设置任务的优先级,则使用队列的默认优先级作为任务的优先级。对于已经设置了优先级的任务,即便优先级大于队列设置的默认优先级,也不会进行修改。
全局最大优先级在配置文件yarn-site.xml中进行设置,例如:
<proerpty>
<name>yarn.cluster.max-application-priority</name>
<value>100</value>
</property>
任务提交时,如果没有指定优先级,使用提交队列的队列默认优先级;但如果指定的优先级超过全局配置的优先级,则使用全局配置的优先级作为任务的优先级。即任务最终的优先级不能大于全局配置的优先级。
【测试验证】
通过向同一个队列,先后提交多个优先级不同的任务,然后在RM的web页面上,观察任务的状态变化及container的分配情况。
从上图可以清楚的看到,优先级为9的任务,其提交时间比优先级为34、优先级为21的任务都要早,但优先级为34、21的任务却优先分配到了资源。(从RM的日志可以更近一步的看到,优先级为34的任务最先分配到资源)
【潜在问题与解决办法】
由于高优先级的任务优先分配资源,假如任务并发运行时,始终有更高优先级的任务在提交,那么低优先级的任务就可能始终无法分配到资源,出现"饿死"的现象。
对于不同用户之间,任务优先级高低引起的饿死问题,可以通过相关配置参数,限制队列中单个用户可使用资源的上限,来解决此问题。
如果是同一用户之间,任务优先级高低引起的饿死问题,目前还没有较好的处理方式。
另外,资源的抢占是一个问题解决的方向,但这个内容比较大,这里不展开说明。
【总结】
本文介绍了容量调度中优先级调度的相关知识,其使用范围局限于同一队列中的不同任务,按照优先级进行调度。
在2.9.0版本中,yarn支持按队列优先级进行调度,即同一父队列下的多个子队列,其优先级各不相同,调度时,按队列优先级排序,优先从优先级更高的队列中选择任务进行调度,有兴趣的小伙伴,可以深入研究。