JobTracker啟動流程原始碼級分析

玖瘋發表於2014-05-08

  org.apache.hadoop.mapred.JobTracker類是個獨立的程式,有自己的main函式。JobTracker是在網路環境中提交及執行MR任務的核心位置。

  main方法主要程式碼有兩句:

1      //建立jobTracker物件
2         JobTracker tracker = startTracker(new JobConf());
3         //啟動各個服務,包括JT內部一些重要的服務或者執行緒
4         tracker.offerService();

  一、startTracker(new JobConf())根據配置檔案啟動JobTracker,這個方法會呼叫startTracker(conf, generateNewIdentifier())方法進行啟動操作,generateNewIdentifier()將會返回一個以節點當前時間格式化成“yyyyMMddHHmm”的字串。

startTracker函式是一個靜態函式,它呼叫JobTracker的建構函式生成一個JobTracker類的例項,建構函式主要工作是對一些重要的變數進行初始化,名為result。然後,進行了一系列初始化活動,包括啟動RPC server,啟動內建的jetty伺服器,檢查是否需要重啟JobTracker等。 
初始化的重要物件包括:
  1、secretManager:DelegationTokenSecretManager的例項,MR安全管理相關類;
  2、aclsManager:ACLsManager的例項,作業級別和佇列級別的管理和訪問許可權控制;
  3、taskScheduler:TaskScheduler的例項,排程器物件,hadoop預設的排程器是FIFO策略的JobQueueTaskScheduler;
  4、interTrackerServer:Server的例項,RPC Server;
  5、infoServer:HttpServer的例項,將Job、Task、TaskTracker相關資訊顯示到WEB前端,封裝的是jetty;
  6、recoveryManager:RecoveryManager的例項,作業恢復管理,即JobTracker啟動時,恢復上次停止時正在執行的作業,並恢復各個任務的執行狀態;recoveryManager.checkAndAddJob(status)會檢查出那些作業需要恢復並放入Set<JobID> jobsToRecover; // set of jobs to be recovered,為後面的recoveryManager.recover()做準備;
  7、jobHistoryServer:JobHistoryServer的例項,用於檢視作業歷史資訊的Server;
  8、dnsToSwitchMapping:
DNSToSwitchMapping的例項,用於構建叢集的網路拓撲結構,它能將節點地址(IP或者host)對映成網路位置。

  二、 tracker.offerService()

 1 /**
 2    * Run forever
 3    */
 4   public void offerService() throws InterruptedException, IOException {
 5     // Prepare for recovery. This is done irrespective of the status of restart
 6     // flag.
 7     while (true) {
 8       try {
 9         recoveryManager.updateRestartCount();
10         break;
11       } catch (IOException ioe) {
12         LOG.warn("Failed to initialize recovery manager. ", ioe);
13         // wait for some time
14         Thread.sleep(FS_ACCESS_RETRY_PERIOD);
15         LOG.warn("Retrying...");
16       }
17     }
18 
19     taskScheduler.start();
20     
21     //  Start the recovery after starting the scheduler
22     try {
23       recoveryManager.recover();
24     } catch (Throwable t) {
25       LOG.warn("Recovery manager crashed! Ignoring.", t);
26     }
27     // refresh the node list as the recovery manager might have added 
28     // disallowed trackers
29     refreshHosts();
30     //用於發現和清理死掉的TaskTracker
31     this.expireTrackersThread = new Thread(this.expireTrackers,
32                                           "expireTrackers");
33     this.expireTrackersThread.start();
34     //用於清理長時間駐留在記憶體中的已經執行完成的作業資訊
35     this.retireJobsThread = new Thread(this.retireJobs, "retireJobs");
36     this.retireJobsThread.start();
37     //用於發現已經被分配給某個TaskTracker但一直未彙報資訊的任務
38     expireLaunchingTaskThread.start();
39 
40     if (completedJobStatusStore.isActive()) {
41       completedJobsStoreThread = new Thread(completedJobStatusStore,
42                                             "completedjobsStore-housekeeper");
43       //將已經執行完成的作業執行資訊儲存到HDFS上,並提供了一套存取這些資訊的API。
44       completedJobsStoreThread.start();
45     }
46 
47     // start the inter-tracker server once the jt is ready
48     this.interTrackerServer.start();
49     
50     synchronized (this) {
51       state = State.RUNNING;
52     }
53     LOG.info("Starting RUNNING");
54     
55     this.interTrackerServer.join();
56     LOG.info("Stopped interTrackerServer");
57   }

   1、首先是不論重啟是什麼狀態都必須要做的recoveryManager.updateRestartCount()更新JobTracker叢集重啟次數,更新檔案${hadoop.tmp.dir}/mapred/system/jobtracker.info。該方法首先判斷如果有restartFile(就是前面說的更新檔案),就刪除tmpRestartFile(不管存在與否);如果不存在restartFile而存在tmpRestartFile,則將tmpRestartFile重新命名為restartFile;如果兩個檔案都沒有可能是第一次啟動也可能是檔案丟失了,這時就不用恢復操作了shouldRecover = false,並且建立一個restartFile寫入0;再讀出restartFile檔案的數字,並+1,建立一個tmpRestartFile將增加後的重啟次數計數器restartCount寫入這個檔案,刪除restartFile檔案,將tmpRestartFile改名為restartFile。這個重啟次數存在的目的官方說法是“The whole purpose of this api is to obtain restart  counts across restarts to avoid attempt-id clashes.”

  2、taskScheduler.start()是啟動排程器。預設的排程器是JobQueueTaskScheduler,其start()方法如下:

 1 //JobQueueTaskScheduler類的start方法主要註冊了兩個非常重要的監聽 器:
 2   //jobQueueJobInProgressListener和eagerTaskInitializationListener。
 3   //前者是 JobQueueJobInProgressListener類的一個例項,該類以先進先出的方式維持一個JobInProgress的佇列,
 4   //並且監聽各 個JobInProgress例項在生命週期中的變化;後者是EagerTaskInitializationListener類的一個例項,
 5   //該類不斷監 聽jobInitQueue,一旦發現有新的job被提交(即有新的JobInProgress例項被加入),
 6   //則立即呼叫該例項的initTasks方 法,對job進行初始化。 
 7   @Override
 8   public synchronized void start() throws IOException {
 9     //呼叫TaskScheduler.start()方法,實際上沒有做任何事情
10     super.start();
11   //註冊一個JobInProgressListerner監聽器 
12     taskTrackerManager.addJobInProgressListener(jobQueueJobInProgressListener);
13     eagerTaskInitializationListener.setTaskTrackerManager(taskTrackerManager);
14     eagerTaskInitializationListener.start();
15     taskTrackerManager.addJobInProgressListener(
16         eagerTaskInitializationListener);
17   }

  taskTrackerManager其實就是JobTracker。eagerTaskInitializationListener.start()會啟動一個執行緒始終監控List<JobInProgress> jobInitQueue一旦發現裡面有新的JobInProgress就構造一個InitJob執行緒放入threadPool執行緒池中執行,該執行緒通過JobTracker.initJob(JobInProgress job)對Job進行初始化。然後向JobTracker註冊eagerTaskInitializationListener。 

  3、recoveryManager.recover()。JobTracker節點由於意外情況而當機的話,那麼可能有一部分Job正在執行,也有一部分Job被使用者成功提交了可還沒有開始被排程執行,那麼當我們重啟JobTracker節點的時候就需要恢復或者重做這些還沒有完成的Job。這裡要說的是RecoveryManager啟動對未完成Job的恢復是在JobTracker節點的主執行緒中完成的,而且是在JobTracker節點的所有後臺執行緒啟動之前,這個呼叫必須要在所有的未完成的Job被完成之後才返回。也就是說,JobTracker的作業恢復管理器在恢復作業的處理過程中,JobTracker節點不會接受客戶端的任何請求,也不接受TaskTracker的任何請求。這個比較複雜以後再講解。

  4、refreshHosts()方法會先重新載入mapred.hosts和mapred.hosts.exclude指定的檔案中主機資訊到相應的Set中;然後從taskTrackers中找出沒在mapred.hosts中但在mapred.hosts.exclude中的taskTracker從相關的資料結構中刪除此taskTracker。節點均以mapred.hosts和mapred.hosts.exclude中的為準。

  5、啟動一個ExpireTrackers執行緒會監控trackerExpiryQueue一旦裡面TaskTracker有超過10分鐘沒有心跳的,JobTracker就認為它死了,將其從相關的資料結構trackerToMarkedTasksMap、trackerToJobsToCleanup、trackerToTasksToCleanup以及trackerToTaskMap刪除。這在lostTaskTracker(TaskTracker taskTracker)方法中進行。

  6、啟動一個RetireJobs執行緒,會將jobs中的完成的job儲存一定時長後,從taskidToTrackerMap、trackerToTaskMap、taskidToTIPMap、jobs、userToJobsMap(每個使用者完成的job數要>100)資料結構中刪除。

  7、啟動一個ExpireLaunchingTasks執行緒,如果一個TaskAttemptID超過10分鐘沒有回報資訊,則JobTracker認為這個task已經失敗,從launchingTasks刪除相關資訊,並將此task狀態標註為FAILED。

  8、啟動一個CompletedJobStatusStore執行緒,預設"mapred.job.tracker.persist.jobstatus.active"是false表示不啟動這個執行緒,如果啟用則需要指定儲存時間"mapred.job.tracker.persist.jobstatus.hours"(預設是0,不儲存)和儲存路徑"mapred.job.tracker.persist.jobstatus.dir"(預設是/jobtracker/jobsInfo)。如果不啟用該執行緒則所有的作業執行資訊全部在記憶體中,且隨著時間及執行任務的增多早期的作業資訊會被刪除。

 

  這樣JobTracker就啟動了。。。。就等著Client提交Job。。。

  參考:1、董西成,《Hadoop技術內幕:深入解析MapReduce架構設計與實現原理》

     2、http://blog.csdn.net/xhh198781/article/details/7354257

相關文章