- worker中为application启动的executor,实际上是启动了这个CoarseGrainedExecutorBackend
- CoarseGrainedExecutorBackend进程启动之后,会立即向driver发送RegisterExecutor消息,
driver注册成功之后,会返回RegisteredExecutor - CoarseGrainedExecutorBackend进程接收到RegisteredExecutor消息会创建Exector对象,作为执行句柄
- Driver内的taskscheduler向CoarseGrainedExecutorBackend发送LaunchTask消息
- Executor的launchTask()方法来启动一个task
- 对于每一个task都会创建一个taskRunner
- 将task封装在一个线程池中(taskRunner),直接将线程丢入线程池执行
CoarseGrainedSchedulerBackend向Executor发送LaunchTask
CoarseGrainedExecutorBackend接收到LaunchTask
// TODO driveractor 发送给executor的消息, 让executor 启动task
case LaunchTask(data) =>
if (executor == null) {
logError("Received LaunchTask command but executor was null")
System.exit(1)
} else {
val ser = env.closureSerializer.newInstance()
val taskDesc = ser.deserialize[TaskDescription](data.value)
logInfo("Got assigned task " + taskDesc.taskId)
/**
* 用内部的执行句柄,Executor的launchTask方法来启动一个task
* TODO 将反序列化后的task放到线程池里
*/
executor.launchTask(this, taskId = taskDesc.taskId, attemptNumber = taskDesc.attemptNumber,
taskDesc.name, taskDesc.serializedTask)
}
=> executor.launchTask
def launchTask(
context: ExecutorBackend,
taskId: Long,
attemptNumber: Int,
taskName: String,
serializedTask: ByteBuffer) {
// 对于每一个task都会创建一个taskRunner 把task的信息封装到TaskRunner里
val tr = new TaskRunner(context, taskId = taskId, attemptNumber = attemptNumber, taskName,
serializedTask)
// 将taskRunner放入内存缓存
runningTasks.put(taskId, tr)
/**
* java ThreadPool,Executor内部有一个线程池
* 将task封装在一个线程池中(taskRunner)直接将线程丢入线程池执行
* 线程池自动实现了排队机制,也就是说,如果线程池内的线程暂时没有空闲,那么丢进去的线程是要排队的
* TODO -> 执行TaskRunner.run方法
*/
threadPool.execute(tr)
}