经过前面文章的SparkContext、DAGScheduler、TaskScheduler分析,再从总体上了解Spark Job的调度流程
主要由以下3个阶段:
1、当有Action作用于某RDD时,该action会作为一个job被提交。在提交的过程中,DAGScheduler模块介入运算,计算RDD之间的依赖关系。RDD之间的依赖关系就形成了DAG。
2、 DAGSchedule的主要功能是接收用户提交的job,将job 根据类型划分为不同的stage,并在每一个stage内产生一系列的task,并将其包装为TaskSet 提交到TaskScheduler上去。
3、 TaskScheduler负责把DAGScheduler分发的任务提交到集群,并运行,同时重新提交失败的task,加快执行慢的task,最终的结果通过事件返回给DAGScheduler。
简单流程如下:
1. 首先应用程序创建SparkContext的实例,如实例为sc
2. 利用SparkContext的实例来创建生成RDD
3. 经过一连串的transformation操作,原始的RDD转换成为其它类型的RDD
4. 当action作用于转换之后RDD时,会调用SparkContext的runJob方法
5. sc.runJob的调用是后面一连串反应的起点,关键性的跃变就发生在此处
调用路径大致如下:
1. sc.runJob->dagScheduler.runJob->submitJob
2. DAGScheduler::submitJob会创建JobSummitted的event发送给内嵌类eventProcessActor
3. eventProcessActor在接收到JobSubmmitted之后调用processEvent处理函数
4. job到stage的转换,生成finalStage并提交运行,关键是调用submitStage
5. 在submitStage中会计算stage之间的依赖关系,依赖关系分为宽依赖和窄依赖两种
6. 如果计算中发现当前的stage没有任何依赖或者所有的依赖都已经准备完毕,则提交task
7. 提交task是调用函数submitMissingTasks来完成
8. task真正运行在哪个worker上面是由TaskScheduler来管理,也就是上面的submitMissingTasks会调用TaskScheduler::submitTasks
9. TaskSchedulerImpl中会根据Spark的当前运行模式来创建相应的backend,如果是在单机运行则创建LocalBackend
10. LocalBackend收到TaskSchedulerImpl传递进来的ReceiveOffers事件,receiveOffers->executor.launchTask->TaskRunner.run