《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
Spark应用程序提交执行时,会根据RDD依赖关系形成有向无环图(DAG),然后交给DAGScheduler进行划分作业和调度阶段,这些作业之间没有依赖关系,对于多个作业之间的调度,Spark提供两种调度策略:一种是FIFO策略,(目前默认的模式);一种是FAIR模式,该模式的调度可以通过两个参数的配置来决定Job执行的优先模式,两个参数分别是minShare(最小任务数)和weight(任务的权重)。该调度策略的执行过程和代码如下:
1.创建调度池
在TaskSchedulerImpl.initilaize方法中先创建根调度池rootPool对象,然后根据系统配置调度模式创建调度创建器,针对两种调度策略具体实例化FIFOSchedulableBuilder或FairSchedulableBuilder,最终使用调度创建器buildPools方法在根调度池rootPool下创建调度池。代码实现如下:
def initialize(backend: SchedulerBackend) {
this.backend = backend
schedulableBuilder = {
//根据调度模式配置调度池
schedulingMode match {
//使用FIFO调度方式
case SchedulingMode.FIFO =>
new FIFOSchedulableBuilder(rootPool)
//使用FAIR调度方式
case SchedulingMode.FAIR =>
new FairSchedulableBuilder(rootPool, conf)
case _ =>
throw new IllegalArgumentException(s"Unsupported $SCHEDULER_MODE_PROPERTY: " +
s"$schedulingMode")
}
}
schedulableBuilder.buildPools()
}
2.调度池加入调度内容
在TaskSchedulerImpl.submitTasks方法中,先把调度阶段拆分为任务集,然后把这些任务集交给管理器TaskManager进行管理,最后把该任务集的管理器加入到调度池中,等待分配执行。
override def submitTasks(taskSet: TaskSet) {
val tasks = taskSet.tasks
logInfo(“Adding task set " + taskSet.id + " with " + tasks.length + " tasks”)
this.synchronized {
//创建任务集的管理,用于管理这个任务集的声明周期
val manager = createTaskSetManager(taskSet, maxTaskFailures)
val stage = taskSet.stageId
val stageTaskSets =
taskSetsByStageIdAndAttempt.getOrElseUpdate(stage, new HashMap[Int, TaskSetManager])
stageTaskSets.foreach { case (_, ts) =>
ts.isZombie = true
}
stageTaskSets(taskSet.stageAttemptId) = manager
//将该任务集的管理器加入到系统调度池中,由系统统一调配,该调度器属于应用级别
//支持FIFO和FAIR(公平调度)两种
schedulableBuilder.addTaskSetManager(manager, manager.taskSet.properties)
…
}
…
}
3.提供已排序的任务集管理器
在TaskSchedulerImpl.resourceOffers方法中进行资源分配时,会从根调度池rootPools获取已经排序的任务管理器,该排序算法由两种调度策略FIFOSchedulingAlgorithm和FairSchedulingAlgorithm的comparator方法提供。代码实现如下:
def resourceOffers(offers: IndexedSeq[WorkerOffer]): Seq[Seq[TaskDescription]] = synchronized {
…
//获取按照资源调度策略排序好的TaskSetManager
val sortedTaskSets = rootPool.getSortedTaskSetQueue
…
}
(1)FIFO调度策略实现代码如下:
private[spark] class FIFOSchedulingAlgorithm extends SchedulingAlgorithm {
override def comparator(s1: Schedulable, s2: Schedulable): Boolean = {
//获取作业优先级,实际上是作业编号
val priority1 = s1.priority
val priority2 = s2.priority
var res = math.signum(priority1 - priority2)
//如果是同一个作业,再比较调度阶段优先级
if (res == 0) {
val stageId1 = s1.stageId
val stageId2 = s2.stageId
res = math.signum(stageId1 - stageId2)
}
res < 0
}
}
(2)FIAR调度策略实现代码如下: