6.1.5 执行任务
TaskTracker申请到新的任务之后,就要在本地运行任务了。运行任务的第一步是将任务本地化(将任务运行所必需的数据、配置信息、程序代码从HDFS复制到TaskTracker本地,见图6-1的步骤⑧)。这主要是通过调用localizeJob()方法来完成的(此方法的具体代码并不复杂,不再列出)。这个方法主要通过下面几个步骤来完成任务的本地化:
1)将job.split复制到本地;
2)将job.jar复制到本地;
3)将job的配置信息写入job.xml;
4)创建本地任务目录,解压job.jar;
5)调用launchTaskForJob()方法发布任务(见图6-1的步骤⑨)。
任务本地化之后,就可以通过调用launchTaskForJob()真正启动起来。接下来launchTaskForJob()又会调用launchTask()方法启动任务。launchTask()方法的主要代码如下:
……
//创建Task本地运行目录
localizeTask(task);
if(this.taskStatus.getRunState()==TaskStatus.State.UNASSIGNED){
this.taskStatus.setRunState(TaskStatus.State.RUNNING);
}
//创建并启动TaskRunner
this.runner=task.createRunner(TaskTracker.this, this);
this.runner.start();
this.taskStatus.setStartTime(System.currentTimeMillis());
……
从代码中可以看出launchTask()方法会先为任务创建本地目录,然后启动TaskRunner。在启动TaskRunner后,对于Map任务,会启动MapTaskRunner;对于Reduce任务则启动ReduceTaskRunner。
之后,TaskRunner又会启动新的Java虚拟机来运行每个任务(见图6-1的步骤⑩)。以Map任务为例,任务执行的简单流程是:
1)配置任务执行参数(获取Java程序的执行环境和配置参数等);
2)在Child临时文件表中添加Map任务信息(运行Map和Reduce任务的主进程是Child类);
3)配置log文件夹,然后配置Map任务的通信和输出参数;
4)读取input split,生成RecordReader读取数据;
5)为Map任务生成MapRunnable,依次从RecordReader中接收数据,并调用Mapper的Map函数进行处理;
6)最后将Map函数的输出调用collect收集到MapOutputBuffer中(见图6-1的步骤11)。