前幾章我們介紹了 Hadoop 的 MapReduce 和 HDFS 兩大組件,內容比較基礎,看完后可以寫簡單的 MR 應用程序,也能夠用命令行或 Java API 操作 HDFS。但要對 Hadoop 做深入的了解,顯然不夠用。因此本章就深入了解一下 MapReduce 應用的運行機制,從而學習 Hadoop 各個組件之間如何配合完成 MR 作業。本章是基於 Hadoop YARN 框架介紹,YARN(Yet Another Resource Negotiator)是 Hadoop 的集群資源管理器,也是 Hadoop2 的默認資源管理器。為什么要用 YARN 框架? 簡單來說 Hadoop1 的時候沒有資源管理器,因此在 Hadoop1 集群只能運行 MR 作業。YARN 出現后統一管理集群的資源,因此 Spark、Storm 等其他分布式計算框架也能運行在 Hadoop 集群。同理,除了 YARN 還有其他的資源管理框架,目前比較火的是 k8s。
運行機制
運行一個 MR 程序主要涉及以下 5 個部分:
- 客戶端: 提交 MR 作業,也就是我們運行 hadoop jar xxx 的命令后,啟動的 Java 程序
- YARN ResourceManager: YARN 集群主節點,負責協調集群上計算資源的分配
- YARN NodeManager:YARN 集群從節點,負責啟動和監視機器上的容器(container)
- MapReduce Application Master:負責協調 MR 作業,當然 Spark 作業也有對應的 application master
運行 MR 任務的工作原理如下圖,本圖摘自《Hadoop 權威指南(第四版)》:
步驟1 是我們在客戶端節點(集群中的某台機器)執行 hadoop jar xxx 命令后,啟動 MR 作業的流程,后續會涉及以下幾個重要流程
- 作業的提交和初始化
- 任務的分配與執行
- 進度和狀態的更新
下面會詳細介紹每個流程。這里我們將編寫的整個 MR 程序叫做作業,MR作業運行后的 map 或 reduce 任務統稱為任務。
任務的提交和初始化
作業的提交
- 向 ResourceManager 申請一個新的應用 ID(步驟 2),之前的 MR 例子我們可以看到,應用 ID 的形式為:application_1551593879638_0009
- 計算作業分片檢查作業的輸入輸出,若輸入文件不可分割或者輸入路徑不存在,報錯返回;如果沒有指定輸出路徑或者輸出路徑已存在,報錯返回
- 將作業運行所需的資源(jar、配置文件和分片信息等)復制到共享文件系統中(步驟 3),默認為 HDFS 。目錄名稱以應用 ID 命名
- 調用 ResourceManager 的 submitApplication() 方法提交作業(步驟4)
以上的流程均在客戶端節點完成。
作業的初始化
ResourceManager 收到調用它的 submitApplication() 方法后,會在 NodeManager 中分配一個 container (步驟 5a),在 container 中啟動 application master(步驟 5b) 。MapReduce application master 的主類是 MRAppMaster。application master 完成初始化后(步驟 6),從共享文件系統(如:HDFS)獲取分片信息(步驟 7)。對每個分片創建一個 map 任務和 reduce 任務,並分配任務 ID。如果 application master 判斷該任務不是 uber 任務,那么接下來會進行任務分配。
任務分配與運行
任務分配
application master 會為 map 任務和 reduce 任務向 ResourceManager 申請分配資源。map 任務的優先級高於 reduce 任務,且直到 5% 的 map 任務完成時,reduce 任務請求才能發出。reduce 任務可以在集群的任意機器執行,但 map 任務有數據本地化的限制,理想情況下數據分片和 map 任務在同一節點運行,即數據本地化(data local),這樣 map 任務直接讀取本地的數據,不需要網絡 IO。如果達不到理想情況,可以在數據節點同一機架上啟動 map 任務,即機架本地化(rack local),這樣 map 任務從同機架上其他節點將數據拷貝到自己的節點。最差的情況是分片和 map 任務不在同一機架,需要跨機架拷貝數據。application master 申請的資源包括內存和 CPU 核心數,申請的大小可以通過 4 個屬性指定:
- mapreduce.map.memory.mb:map 任務內存, 單位:MB,默認:1024
- mapreduce.map.cpu.vcores:map 任務 CPU 核心數,默認:1
- mapreduce.reduce.memory.mb:reduce 任務內存,單位:MB,默認:1024
- mapreduce.reduce.cpu.vcores:reduce 任務 CPU 核心數,默認:1
任務執行
ResourceManager 為任務在某個 NodeManager 上分配容器后(步驟 9a),application master 會與該 NodeManager 通信來啟動容器(步驟 9b)。該任務的主類為 YarnChild,該任務運行前會先將共享文件系統(如:HDFS)上的文件本地化(步驟 10),文件包括:配置文件、JAR包和分布式緩存文件。最后,運行 map 或 reduce 任務(步驟 11)。
進度和狀態更新
當用戶成功提交並且作業成功運行后,用戶希望能夠看到作業的運行狀態。一個作業和它的每個任務都有一個狀態,包括:作業或任務的狀態(比如,運行中、成功或失敗),map 或 reduce 任務的進度以及計數器值等。
- 當 map 或 reduce 任務運行時,通過接口向自己的 application master 上報進度和狀態
- 作業的運行期間,客戶端請求 application master 以獲得最新的狀態
流程圖如下:
作業的完成
application master 接到最后一個任務成功完成的通知后,便把作業置位成功得狀態。可以端查詢到任務成功完成后,從 waitCompletion() 方法返回。作業的統計信息和計數器值輸出在控制台。最后,application master 會做一些清理工作,作業信息由 JobHistoryServer 存檔,以便用戶以后查詢。
小結
本章主要介紹 MR 作業的運行機制,並且了解了 YARN 集群主從節點職責及其相互之間的配合。通過這篇文章的介紹希望讀者對 MR 作業的運行機制有大致的了解。我們可以簡單總結下本章介紹的相關組件的作用。本文主要參考《Hadoop 權威指南(第四版)》和 Hadoop 官方文檔,有興趣的讀者可以深入研究,一起探討。