1 JobTracker启动过程
1.1 各种线程功能
函数offerService()会启动JobTracker内部几个比较重要的后台服务进程,分别是expireTrackersThread、retireJobsThread、expireLaunchingTaskThread和completedJobsStoreThread。相关代码如下:
public class JobTracker { ... ... ExpireLaunchingTasks expireLaunchingTasks = new ExpireLaunchingTasks(); Thread expireLaunchingTaskThread = new Thread(expireLaunchingTasks, "expireLaunchingTasks"); ... ... public void offerService() throws InterruptedException, IOException { ... ... // expireTrackersThread后台服务进程。 this.expireTrackersThread = new Thread(this.expireTrackers, "expireTrackers"); this.expireTrackersThread.start();
// retireJobsThread后台服务进程。 this.retireJobsThread = new Thread(this.retireJobs, "retireJobs"); this.retireJobsThread.start();
// expireLaunchingTaskThread后台服务进程。 expireLaunchingTaskThread.start();
// completedJobsStoreThread后台服务进程。 if (completedJobStatusStore.isActive()) { completedJobsStoreThread = new Thread(completedJobStatusStore, "completedjobsStore-housekeeper"); completedJobsStoreThread.start(); } ... ... } } |
下面分别介绍这几个服务线程。
1) expireTrackersThread线程
该线程主要用于发现和清理死掉的TaskTracker。每个TaskTracker会周期性地通过心跳向JobTracker汇报信息,而JobTracker会记录每个TaskTracker最近的汇报心跳时间。如果某个TaskTracker在10分钟内未汇报心跳,则JobTracker认为它已死掉,并将经的相关信息从数据结构trackToJobsToCleanup、trackerToTasksToCleanup、trackerToMarkedTasksMap中清除,同时将正在运行的任务状态标注为KILLED_UNCLEAN。
2) retireJobsThread线程
该线程主要用于清理长时间驻留在内存中的已经运行完成的作业信息。JobTracker会将已经运行完成的作业信息存放到内存中,以便外部查询,但随着完成的作业越来越多,势必会占用JobTracker的大量内存,为此,JobTracker通过该线程清理驻留在内存中较长时间的已经运行完成的作业信息。
当一个作业满足如下条件1、2或者条件1、3时,将被从数据结构jobs转移到过期作业队列中。
条件1 作业已经运行完成,即运行状态为SUCCESSED、FAILED或KILLED。
条件2 作业完成时间距现在已经超过24小时(可通过参数mapred.jobtracker.retirejob.interval配置)。
条件3 作业拥有者已经完成作业总数超过100(可通过参数mapred.jobtracker.completeuserjobs.maximum配置)个。
过期作业被统一保存到过期队列中。当过期作业超过1000个(可通过参数mapred.job.tracker.retiredjobs.cache.size配置)时,将会从内存中彻底删除。
3) expireLaunchingTaskThread线程
该线程用于发现已经被分配给某个TaskTracker但一直未汇报信息的任务。当JobTracker将某个任务分配给TaskTracker后,如果该任务在10分钟内未汇报进度,则JobTracker认为该任务分配失败,并将其状态标注为FAILED。
4) completedJobsStoreThread线程
该线程将已经运行完成的作业运行信息保存到HDFS上,并提供了一套存取这些信息的API。该线程能够解决以下两个问题。
n 用户无法获取很久之前的作业运行信息:前面提到线程retireJobsThread会清除长时间驻留在内存中的完成作业,这会导致用户无法查询很久之前某个作业的运行信息。
n JobTracker重启后作业运行信息丢失:当JobTracker因故障重启后,所有原本保存到内存中的作业信息将会全部丢失。
该线程通过保存作业运行日志的方式,使得用户可以查询任意时间提交的作业和还原作业的运行信息。
默认情况下,该线程不会启用,可以通过下表所示的几个参数配置并启用该线程。
配置参数 |
参数含义 |
mapred.job.tracker.persist.jobstatus.active |
是否启用该线程 |
mapred.job.tracker.persist.jobstatus.hours |
作业运行信息保存时间 |
mapred.job.tracker.persist.jobstatus.dir |
作业运行信息保存路径 |
1.2 作业恢复
在MapReduce中,JobTracker存在单点故障问题。如果它因异常退出后重启,那么所有正在运行的作业运行时信息将丢失。如果不采用适当的作业恢复机制对作业信息进行恢复,则所有作业需重新提交,且已经计算完成的任务需重新计算。这势必造成资源浪费。
为了解决JobTracker面临的单点故障问题,Hadoop设计了作业恢复机制,过程如下:作业从提交到运行结束的整个过程中,JobTracker会为一些关键事件记录日志(由JobHistory类完成)。对于作业而言,关键事件包括作业提交、作业创建、作业开始运行、作业运行完成、作业运行失败、作业被杀死等;对于任务而言,关键事件包括任务创建、任务开始运行、任务运行结束、任务运行失败、任务被杀死等。当JobTracker因故障重启后(重启过程中,所有TaskTracker仍然活着),如果管理员启用了作业恢复功能(将参数mapred.jobtracker.restart.recover置为true