Spark源码剖析(九):TaskScheduler原理与源码剖析

接着上期内核源码(六)的最后,DAGSchedule会将每个Job划分一系列stage,然后为每个stage创建一批task(数量与partition数量相同),并计算其运行的最佳位置,最后针对这一批task创建一个TaskSet对象,调用submitTasks方法提交TaskSet到TaskSchedule。那么这篇文章我们来剖析TaskScheduler接收到TaskSet后会进行的一系列操作。

Alt text 
  
taskScheduler.submitTasks( 
new TaskSet(tasks.toArray, stage.id, stage.newAttemptId(), stage.jobId, properties))

  1. 创建TaskSetManager负责某一个TaskSet任务执行情况的监控和管理
  2. 调用SparkDeployScheduleBackend的reviveOffers方法。

Alt text 
  
val manager = createTaskSetManager(taskSet, maxTaskFailures)

Alt text 
  
backend.reviveOffers()

Alt text 
  
果然在父类CoarseGrainedSchedulerBackend中找到了reviveOffers方法,发送reviveOffers消息给driverActor。

Alt text 
  
紧接着我们来看看driverActor线程收到reviveOffers消息后如何处理

Alt text 
  
new DriverActor(properties)可以看到DriverActor类是CoarseGrainedSchedulerBackend中的类部类

Alt text 
  
可以看到driverActor线程收到reviveOffers消息后调用了makeOffers()方法:

  1. 调用TaskScheduleImpl的resourceOffers方法,执行任务分配算法,将各个task分配到Executor上去。
  2. 分配好task到executor之后,执行自己的launchTasks方法,将分配的task发送LaunchTask消息 
    到对应的Executor上去,由Executor启动并执行task。

Alt text 
  
new WorkerOffer()代表每个Executor上空闲的资源

Alt text 
  
scheduler.resourceOffers() 任务分配算法入口

Alt text

Alt text 
  
任务分配算法核心: 
双重for循环,第一层遍历所有taskset,第二层遍历每一种本地化级别(从优到劣) 
本地化级别: 
* PROCESS_LOCAL:进程本地化,RDD的partition和task进入同一个Executor内,那么速度当然快 
* NODE_LOCAL:RDD的partition和task在同一个worker节点上 
* NO_PREF:无,没有所谓的本地化级别 
* RACK_LOCAL:机架本地化,RDD的partition和task在同一个机架上 
* ANY:任意的本地化级别

Alt text 
  
launchedTask = resourceOfferSingleTaskSet( 
taskSet, maxLocality, shuffledOffers, availableCpus, tasks)

Alt text

Alt text 
  
taskSet.resourceOffer(execId, host, maxLocality)

Alt text 
  
Scheduler.resourceOffers方法最终会返回已经分配好Executor的任务列表tasks。 
launchTasks方法会接收tasks列表作为参数,通知对应的Executor启动相应的task

Alt text

Alt text

至此TaskSchedule处理TaskSet的流程已经全部结束,我们稍作总结:

  1. 当TaskScheduler接收到从DAGScheduler提交过来的TaskSet时,首先给每个TaskSet都创建一个TaskSetManager负责管理和监控该TaskSet
  2. 接着调用SparkDeployScheduleBackend的reviveOffers方法,经过一系列调用到makeOffers方法
  3. makeOffers方法中的Scheduler.resourceOffers方法会调用TaskScheduleImpl的resourceOffers方法,执行任务分配算法,将各个task分配到Executor上去
  4. makeOffers方法中的launchTasks方法接收已经分配完成的tasks列表,并为每个task发送LaunchTask消息到对应的Executor上去,由Executor启动并执行task

  
下一篇我们将剖析Executor接收到LaunchTask消息后会如何一步步启动Task。

posted @ 2018-01-09 19:16  小丑进场  阅读(805)  评论(1编辑  收藏  举报