==提交Task到Executor=
App->Job->Stage->Task
注:这里Driver、Executor已经都准备好了。
1.Driver端任务提交
org.apache.spark.scheduler.DAGScheduler
--submitMissingTasks
//每一个Task对应处理一个分区的数据,将多个Task放到TaskSet中进行提交
--taskScheduler.submitTasks(new TaskSet)
//在Task之前,创建了TaskSetManager对TaskSet进行封装
--val manager = createTaskSetManager(taskSet, maxTaskFailures)
//将封装好的TaskSetManager放到资源调度器中
//先进先出: org.apache.spark.scheduler.FIFOSchedulableBuilder(默认)
//公平: org.apache.spark.scheduler.FairSchedulableBuilder
--schedulableBuilder.addTaskSetManager(manager, manager.taskSet.properties)
//触发底层资源调度 底层调用的是CoarseGrainedSchedulerBackend.reviveOffers
--backend.reviveOffers()
//给Driver终端发送一条标记位ReviveOffers的消息,
--driverEndpoint.send(ReviveOffers)
--Driver终端会通过receive的方法,接收消息并对其进行处理
#case ReviveOffers =>makeOffers()
//获取可用的Executor
--val activeExecutors = executorDataMap.filterKeys(executorIsAlive)
--val workOffers = activeExecutors.map
// scheduler.resourceOffers(workOffers) 决定Task应该交给哪个Executor处理
--运行Task launchTasks(scheduler.resourceOffers(workOffers))
//因为要将Task提交到Executor运行,所以需要进行序列化
--val serializedTask = ser.serialize(task)
//给Executor终端发送Task
--executorData.executorEndpoint.send(LaunchTask(new SerializableBuffer(serializedTask)))
2.Executor端接收Task并运行
--receive
//对接收到的消息类型进行匹配,匹配LaunchTask
*case LaunchTask(data)
//对接收到的Task进行反序列化
--val taskDesc = ser.deserialize[TaskDescription](data.value)
//运行Task
--executor.launchTask
//从线程池中获取线程,执行task
--threadPool.execute(tr)
--TaskRunner.run
--task.run
--runTask(context)
--ShuffleMapTask // 往磁盘写
--ResultTask // 从磁盘读