一、Task原理
1、Executor接收到LaunchTask消息后,会在TaskRunner中运行一些准备操作,比如反序列化Task、通过网络拉取需要的文件或jar包等;
2、运行task的run方法或者说是runTask方法,这个方法内部最核心的就是调用RDD的iterator()方法,在这里,就会针对RDD的partition执行我们自定义的函数(算子)
3、接下来分两种,ShuffleMapTask和ResultTask
ShuffleMapTask:a、计算完partition数据后,实际上会使用ShuffleManager的ShuffleWriter,将数据写入对应的分区文件
b、所有操作完了,会发送一个MapStatus给DAGScheduler(DAGScheduler里面有一个MapOutputTracker),所有的MapStatus会发送给MapOutputTracker
ResultTask:主要是针对ShuffleMapTask的输出(RDD),来执行Shuffle等操作,包括我们自定义的算子和函数。可能会到MapOutputTracker去拉取需要的ShuffleMapTask输出。
二、源码阅读
从Executor中的TaskRunner开始入手。看run方法:
1、对序列化的task数据,进行反序列化
val (taskFiles, taskJars, taskBytes) = Task.deserializeWithDependencies(serializedTask)/2
2、把文件、jar包拷贝过来
updateDependencies(taskFiles, taskJars)
3、通过正式的反序列化操作,将整个task的数据集反序列化
task = ser.deserialize[Task[Any]](taskBytes, Thread.currentThread.getContextClassLoader)
4、用task的run方法执行task,这个res就是对于ShuffleMapTask来说就是MapStatus,封装了ShuffleMapTask计算的数据的输出位置信息。后面的task就会去联系MapOutputTracker来获取上个ShuffleMapTask的位置拉取数据
val res = task.run( taskAttemptId = taskId, attemptNumber = attemptNumber, metricsSystem = env.metricsSystem)
看下run方法()
创建了一个TaskContextImpl,就是task的上下文,里面记录了task执行的一些全局性变量,比如task重试了几次,属于哪个stage,要处理Rdd哪个partition。然后调用抽象方法runTask(