1.概述
本文是基于spark on yarn的执行分析spark整体执行流程是怎么样的。
我们知道spark程序提交的任务,会拆分成ShuffleMapStage,ResultStage。首先会执行ShuffleMapStage,再执行ResultStage,那么问题来了:
1)当Executor执行SchuffleMapstage任务的时候 driver端在做什么?
2)当一个ShuffleMapStage执行完是如何启动下一个ResultStage的计算?
3) 当一个stage中分区数据量大于executor solt的数量,一个任务完成,如何执行下一个任务?例如:ShuffleMapStage有4分区,此时只有2个executor,只能同时执行两个任务,另外两个再等待。那么这两个等待的任务是何时执行的呢?
2.执行spark任务代码的代码:
看一下需要运行的代码,很简单wordcount。
object WordCount {
def main(args: Array[String]) {
System.setProperty("hadoop.home.dir","C:\\hadoop")
val sparkConf = new SparkConf().setMaster("local").setAppName("wordCount")
sparkConf.set("spark.network.timeout","600")
sparkConf.set("spark.executor.heartbeatInterval","500")
val sc =new SparkContext(sparkConf)
val rdd:RDD[String] = sc.textFile("data/wc.txt",2) //MapPartitionsRDD[1] <-HadoopRDD[0]
val rdd2 = rdd.flatMap{line => line.split(" ")}//MapPartitionsRDD[2]
val rdd3 = rdd2.map{word => word ->1} //MapPartitionsRDD[3]
val rdd4 = rdd3.reduceByKey(_ + _) //ShuffledRDD
println(rdd4.toDebugString)
//触发job执行
rdd4.foreach(println)
Thread.sleep(100000000)
3.执行 时序图:
时序图解释:
(1) 从执行rdd.foreach(println)开始分析,
(2)12步到27步:首先执行shuffleMapTask,执行完成executor给driver发送StatusUpdate(taskId, state, serializedData)消息
(3)28步driver接收到消息,开始处理任务状态更新(源码在下图):
首先,如果stage的所有的partition任务完成,调用submitWaitingChildStages()方法则执行childStage. 执行的步骤是30步到43步 (不包含33-35步)。
另外,如果stage的没有partition任务完成,则继续执行task 。执行步骤为:33步到35步。
4.回答开始的问题:
1)当Executor执行SchuffleMapstage任务的时候 driver端在做什么?
等待executor的StatusUpdate消息,根据消息执行相关操作。
2)当一个ShuffleMapStage执行完是如何启动下一个ResultStage的计算?
executor执行任务完成之后,回调给driver StatusUpdate(taskId, state, serializedData)消息,首先更新stage的状态,如果stage的所有的partition任务完成,调用submitWaitingChildStages()方法则执行childStage。
3) 当一个stage中分区数据量大于executor solt的数量,一个任务完成,如何执行下一个任务?例如:ShuffleMapStage有4分区,此时只有2个executor,只能同时执行两个任务,另外两个再等待。那么这两个等待的任务是何时执行的呢?
executor执行执行任务完成之后,回调给driver StatusUpdate(taskId, state, serializedData)消息,此时会把driver端维护的executor信息中的cup个数和内存给加回去(之前执行任务剪掉部分,再加回去)。 如果stage的没有partition任务完成,则继续执行task.