根據網上相關帖子以及查看部分源代碼,把作業提交流程畫了個流程圖,並對某些步驟做詳細說明,現整理如下:
詳細說明:
一 關於分片
1).分片的原則是:儘量保證一個片的數據不要跨數據節點,因此,最佳實踐爲片的大小與數據塊的大小一致,這也是默認的策略
2).分片算法由FileInput接口定義,所有輸入格式指定類都必須實現此接口;分片的信息寫入文件job.split中,此文件的內容格式如下:
split文件頭,split文件版本號,split的個數
//以下是每個分片的信息
split類型名(默認FileSplit),split的大小,split的內容(對於FileSplit,寫入文件名,此split 在文件中的起始位置),split的location信息(即在那些DataNode上)
二.作業初始化
作業的初始化,主要工作就是初始化任務;
map任務:
1)通過JobClient的readSplitFile()獲取分片信息
2)初始化隊列監聽器EagerTaskInitializationListener把作業(JobInProgress)加入初始化隊列
public void jobAdded(JobInProgress job) {
synchronized (jobInitQueue) {
//加入初始化隊列,這是一個List
jobInitQueue.add(job);
//根據作業優先級對作業進行排序
resortInitQueue();
//通知初始化線程JobInitThread進行初始化
jobInitQueue.notifyAll();
}
}
3)根據分片的數目創建同樣多的map任務管理對象TaskInProgress
4)根據分片數據所在的數據節點位置,綁定任務,即把任務分配給數據所在的節點。但是,只是一個關係映射,並沒有真正的傳輸任務
5)第四步中的這種映射關係存儲在名叫nonRunningMapCache的map結構中,map的定義爲:Map<Node, List<TaskInProgress>>
6.當某個節點有空閒的任務槽的時候,會通過心跳向jobTracker要任務,此時就可以根據自己的節點位置從nonRunningMapCache中獲取任務
reduce任務:
其它跟map相似,只有一下幾點不一樣
1)reduce任務數由JobConf配置指定,通過方法setNumReduceTasks(int num)指定
2)reduce也有一個緩存集合存儲reduce任務管理對象,但是它並不需要對節點進行分配,因爲reduce任務的輸入是map的輸出,會有多個節點輸出,所以不用刻意
補充說明:當作業準備好後,接下來就是作業的分配,作業的分配本質是作業任務的分配,其次,任務分配的過程是針對整個集羣中處於運行狀態的所有作業的分配,根據當前taskTracker節點在機架組織結構中的位置從近到遠獲取任務;
作業分配步驟:
1.taskTracker通過心跳向jobTracker獲取任務
2.jobTracker檢查上一個心跳響應是否完成
3.檢查要啓動的任務數是否超出心跳節點還剩餘的任務槽,超出則不分配
4.檢查即將啓動的任務數和已經啓動的任務數是否超過集羣總的負載能力,如果超出則不分配,不超出則往下執行
5.獲取任務時,是從當前集羣中所有正在運行的作業的所有任務中挑選一個適合自己的任務
6.如果當前節點或者當前節點所在的機架上有任務,則獲取一個
7.如果當前節點或者當前節點所在的機架上沒有可獲取的任務,則從其它機架上獲取任務
參考資料:
1.http://blog.csdn.net/HEYUTAO007/article/details/5725379
2.hadoop權威指南