Spark 中的调度模式主要有两种:FIFO 和 FAIR。默认情况下 Spark 的调度模式是 FIFO(先进先出),谁先提交谁先执行,后面的任务需要等待前面的任务执行。而 FAIR(公平调度)模式支持在调度池中为任务进行分组,不同的调度池权重不同,任务可以按照权重来决定执行顺序。使用哪种调度器由参数 spark.scheduler.mode 来设置,可选的参数有 FAIR 和 FIFO,默认是 FIFO。
在 Scheduler 模块中,当 Stage 划分好,然后提交 Task 的过程中,会进入 TaskSchedulerImpl 的 submitTasks 方法。在代码中有一个 schedulableBuilder 对象,根据用户配置的 SchedulingMode 决定是生成 FIFOSchedulableBuilder 还是生成 FairSchedulableBuilder。在生成 schedulableBuilder 后,调用其 buildPools 方法生成调度池。调度模式由配置参数spark.scheduler.mode(默认值为 FIFO)来确定。
(1) FairSchedulableBuilder
默 认 情 况 下 FAIR 模 式 的 配 置 文 件 是 位 于 SPARK_HOME/conf/fairscheduler.xml 文 件 , 也 可 以 通 过 参 数
spark.scheduler.allocation.file 设置用户自定义配置文件。
fairscheduler.xml 配置的各个参数的含义:
1. name: 该调度池的名称,可根据该参数使用指定 pool。
sc.setLocalProperty("spark.scheduler.pool", "test")
2. weight: 该调度池的权重,各调度池根据该参数分配系统资源。每个调度池得到的资源数为 weight / sum(weight),weight 为 2 的分配到的资源为 weight 为 1 的两倍。
3. minShare: 该调度池需要的最小资源数(CPU 核数)。fair 调度器首先会尝试为每个调度池分配最少 minShare 资源,然后剩余资源才会按照 weight 大小继续分配。
4. schedulingMode: 该调度池内的调度模式。
FAIR 调度池使用方法
如果不加设置,jobs 会提交到 default 调度池中。要想使用自己指定的调度池的话需要通过 SparkContext 对象 sc 来
设置 local 属性:sc.setLocalProperty("spark.scheduler.pool", "test")
设置该参数后,在该 thread 中提交的所有 job 都会提交到 test Pool 中。
如果接下来不再需要使用到该 test 调度池,
sc.setLocalProperty("spark.scheduler.pool", null)
FIFO 和 FAIR 的调度顺序
FIFO 模式的算法类是 FIFOSchedulingAlgorithm,FAIR 模式的算法实现类是 FairSchedulingAlgorithm。具体的调度逻辑是在 comparator 这个方法里面实现的。
FIFO 的调度策略:
如果有两个调度任务 s1 和 s2,首先获得两个任务的 priority,在 FIFO 中该优先级实际上是 Job ID。首先比较两个任务的 Job ID,如果 priority1 比 priority2 小,那么返回 true,表示 s1 的优先级比 s2 的高。我们知道 Job ID 是顺序生成的,先生成的 Job ID 比较小,所以先提交的 job 肯定比后提交的 job 先执行。但是如果是同一个 job 的不同任务,接下来就比较各自的 Stage ID,类似于比较 Job ID,Stage ID 小的优先级高。
FAIR 的调度策略:
(1) 如果 s1 所在 Pool 或者 TaskSetManager 中运行状态的 task 数量比 minShare 小,s2 所在 Pool 或者 TaskSetManager中运行状态的 task 数量比 minShare 大,那么 s1 会优先调度。反之,s2 优先调度。
(2) 如果 s1 和 s2 所在 Pool 或者 TaskSetManager 中运行状态的 task 数量都比各自 minShare 小,那么 minShareRatio小的优先被调度。 minShareRatio 是运行状态 task 数与 minShare 的比值,即比值较少的先被调度。
(3) 如果 minShareRatio 相同,那么最后比较各自 Pool 的名字。