文章目錄
本文是接着上一篇hadoop系列之使用jar命令提交任務
在上一篇我們最後畫了一張圖:
我們再jobClient調用init()函數的時候通過RPC獲得了一個Jobtracker實例。然後在job調用submitJobInternal()的時候又調用了jobtracker的submitJob().接下來我們從submitJob()函數講解jobtracker.
一、Jobtracker啓動
前面說到client通過RPC調用了Jobtracker的submitJob()操作,那Jobtracker作爲RPC的服務端,在啓動的時候又做了哪些事情呢?
Jobtracker是一個獨立的後臺進程,其啓動顯然是要從main函數啓動
public static void main(String argv[]
) throws IOException, InterruptedException {
StringUtils.startupShutdownMessage(JobTracker.class, argv, LOG);
try {
if(argv.length == 0) {
JobTracker tracker = startTracker(new JobConf());
tracker.offerService();
}
else {
if ("-dumpConfiguration".equals(argv[0]) && argv.length == 1) {
dumpConfiguration(new PrintWriter(System.out));
}
else {
System.out.println("usage: JobTracker [-dumpConfiguration]");
System.exit(-1);
}
}
} catch (Throwable e) {
LOG.fatal(StringUtils.stringifyException(e));
System.exit(-1);
}
}
main數裏主要有兩句話:
JobTracker tracker = startTracker(new JobConf()); // 1
tracker.offerService(); // 2
JobTracker tracker = startTracker(new JobConf())` 主要對JobTracker 類進行一些必要的初始化.在初始化過程中有兩個比較關鍵的地方:
- 在
result = new JobTracker(conf, identifier)
的時初始化的時候,做了如下幾件事情:- 初始化secretManager和aclsManager,對安全和用戶權限管理類做初始化
- 通過反射實例化資源調度器 (taskScheduler),實現資源調度器可拔插機制
- 啓動rpc服務器(interTrackerServer)
- 啓動web服務(infoServer)
- 加載用戶配置的job.tracker參數
- 啓動作業恢復管理器(recoveryManager)
- 歷史記錄查看服務啓動(jobHistoryServer)
- 實例化網絡拓撲管理器(dnsToSwitchMapping)
result.taskScheduler.setTaskTrackerManager(result);
將上一步實例化的Jobracker作爲參數反註冊給資源調度器.這裏實質上是使用了觀察者模式,而且是雙向耦合的觀察者模式public static JobTracker startTracker(JobConf conf, String identifier) throws IOException, InterruptedException { DefaultMetricsSystem.initialize("JobTracker"); JobTracker result = null; while (true) { try { result = new JobTracker(conf, identifier); result.taskScheduler.setTaskTrackerManager(result); break; } catch (VersionMismatch e) { throw e; } catch (BindException e) { throw e; } catch (UnknownHostException e) { throw e; } catch (AccessControlException ace) { // in case of jobtracker not having right access // bail out throw ace; } catch (IOException e) { LOG.warn("Error starting tracker: " + StringUtils.stringifyException(e)); } Thread.sleep(1000); } if (result != null) { JobEndNotifier.startNotifier(); MBeans.register("JobTracker", "JobTrackerInfo", result); } return result; }
通過tracker.offerService()
啓動一些重要的後臺進程
- 該方法首先要更新重啓次數.代碼如下.如果更新成功就繼續,更新不成功就再次循環.
while (true) {
try {
recoveryManager.updateRestartCount();
break;
} catch (IOException ioe) {
LOG.warn("Failed to initialize recovery manager. ", ioe);
// wait for some time
Thread.sleep(FS_ACCESS_RETRY_PERIOD);
LOG.warn("Retrying...");
}
}
-
然後是啓動任務調度器,默認的任務調度器是
JobQueueTaskScheduler
.並非一個線程或者進程~~(詳解任務調度器:JobQueueTaskScheduler)~~taskScheduler.start();
start()代碼如下所示,如果有作業被提交給 jobTracker,則
public synchronized void start() throws IOException { super.start(); // 添加JobInProgressListener,這是作業收聽實例。 // 作業收聽實例的作用是監聽作業的提交。 // 下面的taskTrackerManager實際上是JobTracker taskTrackerManager.addJobInProgressListener(jobQueueJobInProgressListener); // 設置並啓動askTrackerManager。 eagerTaskInitializationListener.setTaskTrackerManager(taskTrackerManager); eagerTaskInitializationListener.start(); // 添加eagerTaskInitializationListener作爲作業收聽實例,用於排序 taskTrackerManager.addJobInProgressListener(eagerTaskInitializationListener);
}
```
- tracker.offerService(); 的作用主要就是啓動taskScheduler。此外還啓動了一系列其他的東西。
expireTrackersThread // 發現和清理死掉的TaskTracker
retireJobsThread //清理已經完成的作業信息
expireLaunchingTaskThread // 處理髮送給某個taskTracker但是一直沒有彙報的任務
completedJobsStoreThread // 將已經完成的作業信息保存到hdfs上