原 Hadoop MapReduce 框架的問題
原hadoop的MapReduce框架圖
從上圖中可以清楚的看出原 MapReduce 程序的流程及設計思路:
- 首先用戶程序 (JobClient) 提交了一個 job,job 的信息會發送到 Job Tracker 中,Job Tracker 是 Map-reduce 框架的中心,他需要與集群中的機器定時通信 (heartbeat), 需要管理哪些程序應該跑在哪些機器上,需要管理所有 job 失敗、重啟等操作。
- TaskTracker 是 Map-reduce 集群中每台機器都有的一個部分,他做的事情主要是監視自己所在機器的資源情況。
- TaskTracker 同時監視當前機器的 tasks 運行狀況。TaskTracker 需要把這些信息通過 heartbeat 發送給 JobTracker,JobTracker 會搜集這些信息以給新提交的 job 分配運行在哪些機器上。上圖虛線箭頭就是表示消息的發送 - 接收的過程。
可以看得出原來的 map-reduce 架構是簡單明了的,在最初推出的幾年,也得到了眾多的成功案例,獲得業界廣泛的支持和肯定,但隨着分布式系統集群的規模和其工作負荷的增長,原框架的問題逐漸浮出水面,主要的問題集中如下:
- JobTracker 是 Map-reduce 的集中處理點,存在單點故障。
- JobTracker 完成了太多的任務,造成了過多的資源消耗,當 map-reduce job 非常多的時候,會造成很大的內存開銷,潛在來說,也增加了 JobTracker fail 的風險,這也是業界普遍總結出老 Hadoop 的 Map-Reduce 只能支持 4000 節點主機的上限。
- 在 TaskTracker 端,以 map/reduce task 的數目作為資源的表示過於簡單,沒有考慮到 cpu/ 內存的占用情況,如果兩個大內存消耗的 task 被調度到了一塊,很容易出現 OOM。
- 在 TaskTracker 端,把資源強制划分為 map task slot 和 reduce task slot, 如果當系統中只有 map task 或者只有 reduce task 的時候,會造成資源的浪費,也就是前面提過的集群資源利用的問題。
- 源代碼層面分析的時候,會發現代碼非常的難讀,常常因為一個 class 做了太多的事情,代碼量達 3000 多行,,造成 class 的任務不清晰,增加 bug 修復和版本維護的難度。
- 從操作的角度來看,現在的 Hadoop MapReduce 框架在有任何重要的或者不重要的變化 ( 例如 bug 修復,性能提升和特性化 ) 時,都會強制進行系統級別的升級更新。更糟的是,它不管用戶的喜好,強制讓分布式集群系統的每一個用戶端同時更新。這些更新會讓用戶為了驗證他們之前的應用程序是不是適用新的 Hadoop 版本而浪費大量時間。
新 Hadoop Yarn 框架原理及運作機制
從業界使用分布式系統的變化趨勢和 hadoop 框架的長遠發展來看,MapReduce 的 JobTracker/TaskTracker 機制需要大規模的調整來修復它在可擴展性,內存消耗,線程模型,可靠性和性能上的缺陷。在過去的幾年中,hadoop 開發團隊做了一些 bug 的修復,但是最近這些修復的成本越來越高,這表明對原框架做出改變的難度越來越大。
為從根本上解決舊 MapReduce 框架的性能瓶頸,促進 Hadoop 框架的更長遠發展,從 0.23.0 版本開始,Hadoop 的 MapReduce 框架完全重構,發生了根本的變化。新的Hadoop MapReduce 框架命名為 MapReduceV2 或者叫 Yarn,其架構圖如下圖所示:
重構根本的思想是將 JobTracker 兩個主要的功能分離成單獨的組件,這兩個功能是資源管理(ResourceManager)和任務調度 / 監控。新的資源管理器全局管理所有應用程序計算資源的分配,每一個應用的 ApplicationMaster 負責相應的調度和協調。一個應用程序無非是一個單獨的傳統的 MapReduce job或者是一個 DAG( 有向無環圖 ) job。ResourceManager 和每一台機器的節點管理服務器(NodeManager)能夠管理用戶在那台機器上的進程並能對計算進行組織。
ResourceManager協調集群的資源利用,任何client或者運行着的applicatitonMaster想要運行job或者task都得向RM申請一定的資源。ApplicatonMaster是一個框架特殊的庫,對於MapReduce框架而言有它自己的AM實現,用戶也可以實現自己的AM,在運行的時候,AM結合從 ResourceManager 獲得的資源與NM一起來啟動和監視tasks。
ResourceManager
ResourceManager作為資源的協調者有兩個主要的組件:Scheduler和ApplicationsManager(AsM)。
Scheduler負責分配最少但滿足application運行所需的資源量給Application。Scheduler只是基於應用程序資源的使用情況進行調度,資源包括:內存,CPU,磁盤,網絡等等,可以看出,這同現 Mapreduce 固定類型的資源使用模型有顯著區別,它給集群的使用帶來負面的影響。從某種意義上講它就是一個純粹的調度器,並不負責監視/跟蹤application的狀態,當然也不會處理失敗的task。RM使用resource container概念來管理集群的資源,每一個應用程序需要不同類型的資源因此就需要不同的容器。resource container是資源的抽象,每個container包括一定的內存、IO、網絡等資源,不過目前的實現只包括內存一種資源。ResourceManager 提供一個調度策略的插件,它負責將集群資源分配給多個隊列和應用程序。調度插件可以基於現有的能力調度和公平調度模型。 ResourceManager 支持分層級的應用隊列,這些隊列享有集群一定比例的資源。
ApplicationsManager(AsM)負責處理client提交的job以及協商第一個container以供applicationMaster運行,並且在applicationMaster失敗的時候會重新啟動applicationMaster。下面闡述RM具體完成的一些功能。
- 資源調度:Scheduler從所有運行着的application收到資源請求后構建一個全局的資源分配計划,然后根據application特殊的限制以及全局的一些限制條件分配資源。
- 資源監視:Scheduler會周期性的接收來自NM的資源使用率的監控信息,另外applicationMaster可以從Scheduler得到屬於它的已完成的container的狀態信息。
- Application提交:
- client向AsM獲得一個applicationID
- client將applicationID以及需要的jar包文件等上傳到hdfs的指定目錄,由yarn-site.xml的yarn.app.mapreduce.am.staging-dir指定
- client構造資源請求的對象以及application的提交上下文發送給AsM
- AsM接收application的提交上下文
- AsM根據application的信息向Scheduler協商一個Container供applicationMaster運行,然后啟動applicationMaster
- 向該container所屬的NM發送launchContainer信息啟動該container,也即啟動applicationMaster、AsM向client提供運行着的AM的狀態信息。
4. AM的生命周期:AsM負責系統中所有AM的生命周期的管理。AsM負責AM的啟動,當AM啟動后,AM會周期性的向AsM發送heartbeat,默認是1s,AsM據此了解AM的存活情況,並且在AM失敗時負責重啟AM,若是一定時間過后(默認10分鍾)沒有收到AM的heartbeat,AsM就認為該AM失敗了。
NodeManager
NM是每一台機器框架的代理,主要負責啟動RM分配給AM的container以及代表AM的container,並且會監視container的運行情況。在啟動container的時候,NM會設置一些必要的環境變量以及將container運行所需的jar包、文件等從hdfs下載到本地,也就是所謂的資源本地化;當所有准備工作做好后,才會啟動代表該container的腳本將程序啟動起來。啟動起來后,NM會周期性的監視該container運行占用的資源情況 (CPU,內存,硬盤,網絡 ) 並且向調度器匯報,若是超過了該container所聲明的資源量,則會kill掉該container所代表的進程。
另外,NM還提供了一個簡單的服務以管理它所在機器的本地目錄。Applications可以繼續訪問本地目錄即使那台機器上已經沒有了屬於它的container在運行。例如,Map-Reduce應用程序使用這個服務存儲map output並且shuffle它們給相應的reduce task。
在NM上還可以擴展自己的服務,yarn提供了一個yarn.nodemanager.aux-services的配置項,通過該配置,用戶可以自定義一些服務,例如Map-Reduce的shuffle功能就是采用這種方式實現的。
NM在本地為每個運行着的application生成如下的目錄結構:
Container目錄下的目錄結構如下:
在啟動一個container的時候,NM就執行該container的default_container_executor.sh,該腳本內部會執行launch_container.sh。launch_container.sh會先設置一些環境變量,最后啟動執行程序的命令。對於MapReduce而言,啟動AM就執行org.apache.hadoop.mapreduce.v2.app.MRAppMaster;啟動map/reduce task就執行org.apache.hadoop.mapred.YarnChild。
ApplicationMaster
ApplicationMaster是一個框架特殊的庫,每一個應用的 ApplicationMaster 的職責有:向調度器索要適當的資源容器,運行任務,跟蹤應用程序的狀態和監控它們的進程,處理任務的失敗原因。
對於Map-Reduce計算模型而言有它自己的ApplicationMaster實現,對於其他的想要運行在yarn上的計算模型而言,必須得實現針對該計算模型的ApplicationMaster用以向RM申請資源運行task,比如運行在yarn上的spark框架也有對應的ApplicationMaster實現,歸根結底,yarn是一個資源管理的框架,並不是一個計算框架,要想在yarn上運行應用程序,還得有特定的計算框架的實現。由於yarn是伴隨着MRv2一起出現的,所以下面簡要概述MRv2在yarn上的運行流程。
MRv2運行流程:
- MR JobClient向resourceManager(AsM)提交一個job
- AsM向Scheduler請求一個供MR AM運行的container,然后啟動它
- MR AM啟動起來后向AsM注冊
- MR JobClient向AsM獲取到MR AM相關的信息,然后直接與MR AM進行通信
- MR AM計算splits並為所有的map構造資源請求
- MR AM做一些必要的MR OutputCommitter的准備工作
- MR AM向RM(Scheduler)發起資源請求,得到一組供map/reduce task運行的container,然后與NM一起對每一個container執行一些必要的任務,包括資源本地化等
- MR AM 監視運行着的task 直到完成,當task失敗時,申請新的container運行失敗的task
- 當每個map/reduce task完成后,MR AM運行MR OutputCommitter的cleanup 代碼,也就是進行一些收尾工作
- 當所有的map/reduce完成后,MR AM運行OutputCommitter的必要的job commit或者abort APIs
- MR AM退出。
在Yarn上寫應用程序
在yarn上寫應用程序並不同於我們熟知的MapReduce應用程序,必須牢記yarn只是一個資源管理的框架,並不是一個計算框架,計算框架可以運行在yarn上。我們所能做的就是向RM申請container,然后配合NM一起來啟動container。就像MRv2一樣,jobclient請求用於MR AM運行的container,設置環境變量和啟動命令,然后交由NM去啟動MR AM,隨后map/reduce task就由MR AM全權負責,當然task的啟動也是由MR AM向RM申請container,然后配合NM一起來啟動的。所以要想在yarn上運行非特定計算框架的程序,我們就得實現自己的client和applicationMaster。另外我們自定義的AM需要放在各個NM的classpath下,因為AM可能運行在任何NM所在的機器上。
新舊 Hadoop MapReduce 框架比對
讓我們來對新舊 MapReduce 框架做詳細的分析和對比,可以看到有以下幾點顯著變化:
首先客戶端不變,其調用 API 及接口大部分保持兼容,這也是為了對開發使用者透明化,使其不必對原有代碼做大的改變 ( 詳見 2.3 Demo 代碼開發及詳解),但是原框架中核心的 JobTracker 和 TaskTracker 不見了,取而代之的是 ResourceManager, ApplicationMaster 與 NodeManager 三個部分。
我們來詳細解釋這三個部分,首先 ResourceManager 是一個中心的服務,它做的事情是調度、啟動每一個 Job 所屬的 ApplicationMaster、另外監控 ApplicationMaster 的存在情況。細心的讀者會發現:Job 里面所在的 task 的監控、重啟等等內容不見了。這就是 AppMst 存在的原因。ResourceManager 負責作業與資源的調度。接收 JobSubmitter 提交的作業,按照作業的上下文 (Context) 信息,以及從 NodeManager 收集來的狀態信息,啟動調度過程,分配一個 Container 作為 App Mstr
NodeManager 功能比較專一,就是負責 Container 狀態的維護,並向 RM 保持心跳。
ApplicationMaster 負責一個 Job 生命周期內的所有工作,類似老的框架中 JobTracker。但注意每一個 Job(不是每一種)都有一個 ApplicationMaster,它可以運行在 ResourceManager 以外的機器上。
Yarn 框架相對於老的 MapReduce 框架什么優勢呢?我們可以看到:
- 這個設計大大減小了 JobTracker(也就是現在的 ResourceManager)的資源消耗,並且讓監測每一個 Job 子任務 (tasks) 狀態的程序分布式化了,更安全、更優美。
- 在新的 Yarn 中,ApplicationMaster 是一個可變更的部分,用戶可以對不同的編程模型寫自己的 AppMst,讓更多類型的編程模型能夠跑在 Hadoop 集群中,可以參考 hadoop Yarn 官方配置模板中的 mapred-site.xml 配置。
- 對於資源的表示以內存為單位 ( 在目前版本的 Yarn 中,沒有考慮 cpu 的占用 ),比之前以剩余 slot 數目更合理。
- 老的框架中,JobTracker 一個很大的負擔就是監控 job 下的 tasks 的運行狀況,現在,這個部分就扔給 ApplicationMaster 做了,而 ResourceManager 中有一個模塊叫做 ApplicationsManager( 注意不是 ApplicationMaster),它是監測 ApplicationMaster 的運行狀況,如果出問題,會將其在其他機器上重啟。
- Container 是 Yarn 為了將來作資源隔離而提出的一個框架。這一點應該借鑒了 Mesos 的工作,目前是一個框架,僅僅提供 java 虛擬機內存的隔離 ,hadoop 團隊的設計思路應該后續能支持更多的資源調度和控制 , 既然資源表示成內存量,那就沒有了之前的 map slot/reduce slot 分開造成集群資源閑置的尷尬情況。
新的 Yarn 框架相對舊 MapRduce 框架而言,其配置文件 , 啟停腳本及全局變量等也發生了一些變化,主要的改變如下:
表 1. 新舊 Hadoop 腳本 / 變量 / 位置變化表
改變項 | 原框架中 | 新框架中(Yarn) | 備注 |
---|---|---|---|
配置文件位置 | ${hadoop_home_dir}/conf | ${hadoop_home_dir}/etc/hadoop/ | Yarn 框架也兼容老的 ${hadoop_home_dir}/conf 位置配置,啟動時會檢測是否存在老的 conf 目錄,如果存在將加載 conf 目錄下的配置,否則加載 etc 下配置 |
啟停腳本 | ${hadoop_home_dir}/bin/start(stop)-all.sh | ${hadoop_home_dir}/sbin/start(stop)-dfs.sh ${hadoop_home_dir}/bin/start(stop)-all.sh |
新的 Yarn 框架中啟動分布式文件系統和啟動 Yarn 分離,啟動 / 停止分布式文件系統的命令位於 ${hadoop_home_dir}/sbin 目錄下,啟動 / 停止 Yarn 框架位於 ${hadoop_home_dir}/bin/ 目錄下 |
JAVA_HOME 全局變量 | ${hadoop_home_dir}/bin/start-all.sh 中 | ${hadoop_home_dir}/etc/hadoop/hadoop-env.sh ${hadoop_home_dir}/etc/hadoop/Yarn-env.sh |
Yarn 框架中由於啟動 hdfs 分布式文件系統和啟動 MapReduce 框架分離,JAVA_HOME 需要在 hadoop-env.sh 和 Yarn-env.sh 中分別配置 |
HADOOP_LOG_DIR 全局變量 | 不需要配置 | ${hadoop_home_dir}/etc/hadoop/hadoop-env.sh | 老框架在 LOG,conf,tmp 目錄等均默認為腳本啟動的當前目錄下的 log,conf,tmp 子目錄 Yarn 新框架中 Log 默認創建在 Hadoop 用戶的 home 目錄下的 log 子目錄,因此最好在 ${hadoop_home_dir}/etc/hadoop/hadoop-env.sh 配置 HADOOP_LOG_DIR,否則有可能會因為你啟動 hadoop 的用戶的 .bashrc 或者 .bash_profile 中指定了其他的 PATH 變量而造成日志位置混亂,而該位置沒有訪問權限的話啟動過程中會報錯 |
由於新的 Yarn 框架與原 Hadoop MapReduce 框架相比變化較大,核心的配置文件中很多項在新框架中已經廢棄,而新框架中新增了很多其他配置項,看下表所示會更加清晰:
參考:
更快、更強——解析Hadoop新一代MapReduce框架Yarn
MapReduce和YARN的關系 - Hadoop分布式數據分析平台
hadoop2提交到Yarn: Mapreduce執行過程分析1