Spark1.6.3 Driver端 task运行完成源码分析

原创 2017年01月03日 11:04:30
0.背景
0.1当完成task调度:
Executor就会收到serialized的 task,先deserialize 出正常的task,然后运行task得到结果,并通过状态更新的RPC告知SchedulerBackend
0.2这里主要分析GoarseGrainedSchedulerBackend.scala的情况



1.GoarseGrainedSchedulerBackend.scala 接收task完成信息

1.1 receive()函数:
接收到StatusUpdate(executorId, taskId, state, data)事件后,会把这个事件继续转到taskSchedulerImpl,调用scheduler.statusUpdate(taskId, state, data.value).
1.2 参数:
(1) state表示task的状态,这里主要讨论FINISHED的情况,如果task完成,就会运行makeOffers(executorId)继续调度剩余的task。
(2) data表示executor端传递过来的serializedData。



2.TaskSchedulerImpl.scala 初步接收task完成信息

具体分析statusUpdate(tid, state, serializedData):
2.1 taskIdToTaskSerManager.get(tid) match {......}
根据taskId推出它所属于的taskSetManager
2.2 taskSet.removeRunningTask(tid)
      taskResultGetter.enqueueSuccessfulTask(taskSet, tid, serializedData)
更新相关数据结构,然后使用taskResultGetter对serializedData进行反序列化



3.taskResultGetter.scala 反序列化task结果

具体分析enqueueSuccessfulTask(taskSetManager, tid, serializedData)
3.1 val (result, size) = serializer.get().deserialized[TaskResult[_]](serializedData) match{......}
调用serializer将serializedData进行反序列化,这里分两种情况,说明如下:当 task在Executor端完成后会返回其执行结果 result,并且这个结果要荣国Actor发送到driver端。但Actor发送的数据包不宜过大,因此:
(1) 当result不大时,serializedData保存的直接序列化的结果,也就是 case directResult: DirectTaskResult[_] =>,最后直接获得(directResult, serializedData.limit())
(2) 如果 result 比较大, serializedData保存的是结果存储位置blockId和结果大小size,也就是 case IndirectTaskResult(blockId, size),然后driver端会调用sparkEnv.blockManager.getRemoteBytes(blockId)通过HTTP的方式去获取serializedTaskResult,再进行第二次反序列化获得deserializedResult, 最后获得(deserializedResult, size).
3.2 scheduler.handleSuccessfulTask(taskSetManager, tid, result)
经过taskResultGetter.scala的反序列化后在回到TaskSchedulerImpl.scala



4.TaskSchedulerImpl.scala 再次接收task完成信息

taskSetManager.handleSuccessfulTask(tid, taskResult)将把task完成信息送到所属的TaskSetManager中进行处理



5.TaskSetManager.scala 接收task完成信息

具体分析handleSuccessfulTask(tid, result)
5.1 val info = taskIndos(tid) ...... removeRunningTask(tid):
更新task相关数据结构
5.2 sched.dagScheduler.taskEnded(......)
将task完成的信息告知dagScheduler
5.3 if(!successful(index)) {......}
更新有关taskSet完成的数据结构
5.4 maybeFinishTaskSet()
判断taskSet是否以及完成,如果完成则调用sched.taskSetFinished(this),来告知上层的taskSchedulerImpl.scala



6.TaskSchedulerImpl.scala 接收taskSet完成信息(optional)


首先更新管理taskSets的数据结构taskSetsByStageIdAndAttempt, 然后调用manager.parent.removeSchedulable(manger)将这个taskSet从调度池中删除



7.DAGScheduler.scala 接收task完成信息

7.1 eventProcessloop:
会post出一个CompletionEvent的事件,这个事件会被DAGScheduler.scala中的doOnReveive接受并处理,然后调用dagScheduler.handleTaskCompletion(completion)

。。。。。。

7.2 分析dagScheduler.handleTaskCompletion(completion)
(1) case Success => 
          ListenerBus.post(SparkListenerTaskEnd(......))
向ListenerBus上广播taskEnd的事件,按需被接收,关于ListenerBus有待后续分析
(2) stage.pendingPartitons -= task.partitionId
task的完成表示stage最后阶段RDD的一个partition已经获得,因此更新数据结构
(3) task match {
     case rt: ResultTask[_, _] => 
     .......
     markStageAsFinished(resultStage)
     cleanupStageForJobAndIndependentStage(job)
     ListenerBus.post(SparkListenerJobEnd)
如果task是ResultTask,会判断所属Job是否完成,如果完成,首先调用markStageAsFinished来post相关stage完成事件,具体实现为内部的ListenerBus.post(SparkListenerStageCompleted(......));然后调用cleanupStageForJobAndIndependentStage并根据是否有其他job需要这个stage来更新相关数据结构,主要有jobIdToStageIds和stageIdToStage;最后post出job完成的事件
(4) case smt: ShuffleMapTask =>
和上面类似,只是没有post出job完成的事件



8.画图总结

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

37 Spark之Task执行原理及结果

第三十七课 Spark之Task执行原理及结果 主要内容 1. Task执行原理流程图 2. Task执行源码 3. Task执行结果在Driver端的处理...

Spark1.6.3 Driver端 task调度源码分析

0.背景 当一个Action操作触发了Spark Job提交后: 1. Spark首先会在DAGScheduler.scala 中对其stages进行递归分析 2. 然后针对某个可执行的stage,根...

32 Spark中的Executor工作原理

内容: 1. Spark Executor 工作原理 2. ExecutorBackend 注册 3. Executor实例化 4. Executor 具体工作流程...

Spark源码分析之七:Task运行(一)

在Task调度相关的两篇文章《Spark源码分析之五:Task调度(一)》与《Spark源码分析之六:Task调度(二)》中,我们大致了解了Task调度相关的主要逻辑,并且在Task调度逻辑的最后,C...

Spark源码分析之八:Task运行(二)

在《Spark源码分析之七:Task运行(一)》一文中,我们详细叙述了Task运行的整体流程,最终Task被传输到Executor上,启动一个对应的TaskRunner线程,并且在线程池中被调度执行。...

spark core源码分析10 Task的运行

这一节介绍具体task的运行以及最终结果的处理 看线程运行的run方法,见代码注释 override def run(): Unit = { val taskMemoryManager = ...

Spark源码系列之Spark内核——Task运行

在详细介绍前,还是让我们先看看Task运行的流程,先有个整体的感觉: Executor收到序列化的Task后,先反序列化取出正常的Task,然后运行Task得到执行结果directResul...

Spark Streaming源码分析之Receiver在Driver的实现全生命周期

Spark streaming 程序需要不断接收新数据,然后进行业务逻辑处理,而用于接受数据的就是Recever。显然Receiver的正常运行对应整个Spark Streaming应用程序至关重要...

Spark1.3从创建到提交:6)Executor和Driver互动源码分析

上一节介绍了worker启动了一个名为CoarseGrainedExecutorBackend的进程,首先看下CoarseGrainedExecutorBackend类的main方法 def main...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spark1.6.3 Driver端 task运行完成源码分析
举报原因:
原因补充:

(最多只允许输入30个字)