我们知道SetupCompletedTransition中会去调度Task.
job.scheduleTasks(job.mapTasks,job.numReduceTasks ==0);
job.scheduleTasks(job.reduceTasks,true);
如果没有Task了,新建Job_COMPLETED事件,然后交给事件分发器处理。
我们看一下shcheduleTasks的过程:
# 遍历所有TaskId
# 根据TaskId从集合completedTasksFromPreviousRun中移除对应的元素,并获取被移除的元素
# 构造T_SCHEDULE任务调度事件,交给事件处理器处理
然后就会调到TaskImpl中静态内部类InitialScheduleTransition#transi
tion方法
#添加并调度TaskAttempt
task.addAndScheduleAttempt(Avataar.VIRGIN);
# 设置任务的调度时间为当前时间
task.scheduledTime =task.clock.getTime();
# 发送任务启动事件
task.sendTaskStartedEvent();
添加和调度Task Attempt的流程如下:
TaskAttemptattempt = addAttempt(avataar);
inProgressAttempts.add(attempt.getID());
# 创建TaskAttempt实例
# 把当前TaskAttempt的id添加到正在运行的TaskAttempt集合inProgressAttempts中
# 调度TaskAttempt: 如果集合failedAttempts大小大于0说明,该Task之前有TaskAttempts失败的情形,此次为重新调度,此时事件为TA_RESCHEDULE否则事件为TA_SCHEDULE
创建TaskAttempts,会调用createAttempt方法,该方法会根据Task类型,去创建不同的TaskAttemptImpl实例,比如当前是MapTask,会创建MapTaskAttemptImpl,如果当前是ReduceTask,那么此时就会创建ReduceTaskAttemptImpl
TaskAttempt生成了,就需要调度了,我们此时在看TA_RESCHEDULE
或者TA_SCHEDULE
它是由RequestContainerTransition的transition方法处理的,流程如下:
#申请容器
如果TaskAttempt是重新调度,构造容器申请事件:ContainerRequest
Event;如果是第一次调度,构造容器申请事件ContainerRequestEvent
区别:reschedule不需要考虑Node和Lock为指数型;因为此时Attempt之前已经失败了,此时应当以能够完成Attempt为首要任务;