Hadoop學習(二)——MapReduce\Yarn架構

Hiway發表於2019-02-20

其他更多java基礎文章:
java基礎學習(目錄)


學習資料
理解Hadoop YARN架構

本文先講MapReduce 1.x的框架。再講MapReduce 1.x升級改進後MapReduce 2.x/Yarn的框架。目前主要是用MapReduce 2.x/Yarn的框架。

MapReduce 1.x

MapReduce 1.x重點概念

Hadoop學習(二)——MapReduce\Yarn架構

JobClient

使用者編寫的MapReduce程式通過Client提交到JobTracker端;同時,使用者可通過Client提供的一些介面檢視作業執行狀態。在Hadoop內部用“作業” (Job)表示MapReduce程式。每一個Job都會在使用者端通過Client類將應用程式以及引數配置Configuration打包成Jar檔案儲存在HDFS,並把路徑提交到JobTracker,然後由JobTracker建立每一個Task(即MapTask和ReduceTask),將它們分發到各個TaskTracker服務中去執行。

JobClient提交Job的詳細流程主要如下:

Hadoop學習(二)——MapReduce\Yarn架構
JobClient在獲取了JobTracker為Job分配的id之後,會在JobTracker的系統目錄(HDFS)下為該Job建立一個單獨的目錄,目錄的名字即是Job的id,該目錄下會包含檔案job.xml、job.jar、job.split等,其中,job.xml檔案記錄了Job的詳細配置資訊,job.jar儲存了使用者定義的關於job的map、reduce操縱,job.split儲存了job任務的切分資訊。

JobTracker

JobTracker 主要負責資源監控和作業排程。JobTracker 監控所有 TaskTracker 與作業Job的健康狀況,一旦發現失敗情況後,其會將相應的任務轉移到其他節點;同時,JobTracker 會跟蹤任務的執行進度、資源使用量等資訊,並將這些資訊告訴任務排程器,而排程器會在資源出現空閒時,選擇合適的任務使用這些資源。在Hadoop 中,任務排程器是一個可插拔的模組,使用者可以根據自己的需要設計相應的排程器。

以下引用 www.aboutyun.com/thread-7778…

JobTracker為作業的提交做了兩件事:一.為作業生成一個Job;二.接受該作業。 我們都知道,客戶端的JobClient把作業的所有相關資訊都儲存到了JobTracker的系統目錄下(當然是HDFS了),這樣做的一個最大的好處就是客戶端幹了它所能幹的事情同時也減少了伺服器端JobTracker的負載。下面就來看看JobTracker是如何來完成客戶端作業的提交的吧!哦。對了,在這裡我不得不提的是客戶端的JobClient向JobTracker正式提交作業時直傳給了它一個改作業的JobId,這是因為與Job相關的所有資訊已經存在於JobTracker的系統目錄下,JobTracker只要根據JobId就能得到這個Job目錄。

Hadoop學習(二)——MapReduce\Yarn架構
對於上面的Job的提交處理流程,我將簡單的介紹以下幾個過程:

  1. 建立Job的JobInProgress
    JobInProgress物件詳細的記錄了Job的配置資訊,以及它的執行情況,確切的來說應該是Job被分解的map、reduce任務。在JobInProgress物件的建立過程中,它主要乾了兩件事,一是把Job的job.xml、job.jar檔案從Job目錄copy到JobTracker的本地檔案系統(job.xml->/jobTracker/jobid.xml,job.jar->/jobTracker/jobid.jar);二是建立JobStatus和Job的mapTask、reduceTask存佇列來跟蹤Job的狀態資訊。
  2. 檢查客戶端是否有許可權提交Job
    JobTracker驗證客戶端是否有許可權提交Job實際上是交給QueueManager來處理的。
  3. 檢查當前mapreduce叢集能夠滿足Job的記憶體需求
    客戶端提交作業之前,會根據實際的應用情況配置作業任務的記憶體需求,同時JobTracker為了提高作業的吞吐量會限制作業任務的記憶體需求,所以在Job的提交時,JobTracker需要檢查Job的記憶體需求是否滿足JobTracker的設定。

上面流程已經完畢,可以總結為下圖:

Hadoop學習(二)——MapReduce\Yarn架構

TaskTracker

TaskTracker會週期性地通過心跳機制將本節點上資源的使用情況和任務的執行進度彙報給JobTracker,同時接收JobTracker傳送過來的命令並執行相應的操作(如啟動新任務、殺死 任務等)。TaskTracker 使用“slot”等量劃分本節點上的資源量。 “slot”代表計算資源(CPU、 記憶體等)。一個 Task 獲取到一個slot 後才有機會執行,而Hadoop排程器的作用就是將各個TaskTracker上的空閒slot分配給Task使用。slot分為Map slot和Reduce slot 兩種,分別供Map Task和Reduce Task使用。TaskTracker通過slot數目(可配置引數)限定Task的併發度。

這裡可能有人會混淆JobTracker、TaskTracker和Hadoop學習(一)——hdfs架構中所講的的DataNode、NameNode。其實JobTracker對應於NameNode,TaskTracker對應於DataNode。DataNode和NameNode是針對資料存放來而言的,JobTracker和TaskTracker是對於MapReduce執行而言的。

MapTask和ReduceTask

Task 分為 Map Task 和 Reduce Task 兩種,均由TaskTracker啟動。從Hadoop學習(一)——hdfs架構中我們知道,HDFS以固定大小的block 為基本單位儲存資料,而對於MapReduce的輸入而言,其處理單位是split。 split 與 block 的對應關係預設是1:1。split 是一個邏輯概念,它只包含一些後設資料資訊,比如資料起始位置、資料長度、資料所在節點等。它的劃分方法完全由使用者自己決定。但需要注意的是,split的多少決定了Map Task的數目,因為每個split會交由一個Map Task處理。split會在後面MapReduce的執行過程中詳細講。

MapReduce 1.x工作流程

www.aboutyun.com/thread-1549…

整個MapReduce作業的工作過程,如下所示:

Hadoop學習(二)——MapReduce\Yarn架構

  1. 作業的提交 JobClient的submitJob()方法實現的作業提交過程,如下所示: 通過JobTracker的getNewJobId()請求一個新的作業ID;(2) 檢查作業的輸出說明(比如沒有指定輸出目錄或輸出目錄已經存在,就丟擲異常); 計算作業的輸入分片(當分片無法計算時,比如輸入路徑不存在等原因,就丟擲異常); 將執行作業所需的資源(比如作業Jar檔案,配置檔案,計算所得的輸入分片等)複製到一個以作業ID命名的目錄中。(叢集中有多個副本可供TaskTracker訪問)(3) 通過呼叫JobTracker的submitJob()方法告知作業準備執行。(4)

  2. 作業的初始化 JobTracker接收到對其submitJob()方法的呼叫後,就會把這個呼叫放入一個內部佇列中,交由作業排程器(比如先進先出排程器,容量排程器,公平排程器等)進行排程;(5) 初始化主要是建立一個表示正在執行作業的物件——封裝任務和記錄資訊,以便跟蹤任務的狀態和程式;(5) 為了建立任務執行列表,作業排程器首先從HDFS中獲取JobClient已計算好的輸入分片資訊(6)。然後為每個分片建立一個MapTask,並且建立ReduceTask。(Task在此時被指定ID,請區分清楚Job的ID和Task的ID)。

  3. 任務的分配 TaskTracker定期通過“心跳”與JobTracker進行通訊,主要是告知JobTracker自身是否還存活,以及是否已經準備好執行新的任務等;(7) JobTracker在為TaskTracker選擇任務之前,必須先通過作業排程器選定任務所在的作業; 對於MapTask和ReduceTask,TaskTracker有固定數量的任務槽(準確數量由TaskTracker核的數量和記憶體大小來決定)。JobTracker會先將TaskTracker的MapTask填滿,然後分配ReduceTask到TaskTracker; 對於MapTrask,JobTracker通過會選取一個距離其輸入分片檔案最近的TaskTracker。對於ReduceTask,因為無法考慮資料的本地化,所以也沒有什麼標準來選擇哪個TaskTracker。

  4. 任務的執行 TaskTracker分配到一個任務後,通過從HDFS把作業的Jar檔案複製到TaskTracker所在的檔案系統(Jar本地化用來啟動JVM),同時TaskTracker將應用程式所需要的全部檔案從分散式快取複製到本地磁碟;(8) TaskTracker為任務新建一個本地工作目錄,並把Jar檔案中的內容解壓到這個資料夾中; TaskTracker啟動一個新的JVM(9)來執行每個Task(包括MapTask和ReduceTask),這樣Client的MapReduce就不會影響TaskTracker守護程式(比如,導致崩潰或掛起等); 子程式通過umbilical介面與父程式進行通訊,Task的子程式每隔幾秒便告知父程式它的進度,直到任務完成。

  5. 程式和狀態的更新 一個作業和它的每個任務都有一個狀態資訊,包括作業或任務的執行狀態,Map和Reduce的進度,計數器值,狀態訊息或描述(可以由使用者程式碼來設定)。這些狀態資訊在作業期間不斷改變,它們是如何與Client通訊的呢?

Hadoop學習(二)——MapReduce\Yarn架構

  • 任務在執行時,對其進度(即任務完成的百分比)保持追蹤。對於MapTask,任務進度是已處理輸入所佔的比例。對於ReduceTask,情況稍微有點複雜,但系統仍然會估計已處理Reduce輸入的比例;
  • 這些訊息通過一定的時間間隔由Child JVM—>TaskTracker—>JobTracker匯聚。JobTracker將產生一個表明所有執行作業及其任務狀態的全域性檢視。可以通過Web UI檢視。同時JobClient通過每秒查詢JobTracker來獲得最新狀態,並且輸出到控制檯上。
  1. 作業的完成 當JobTracker收到作業最後一個任務已完成的通知後,便把作業的狀態設定為"成功"。然後,在JobClient查詢狀態時,便知道作業已成功完成,於是JobClient列印一條訊息告知使用者,最後從runJob()方法返回。

MapReduce 1.x的缺點

隨著分散式系統叢集的規模和其工作負荷的增長,原框架的問題逐漸浮出水面,主要的問題集中如下:

  1. JobTracker 是 Map-reduce 的集中處理點,存在單點故障。
  2. JobTracker 完成了太多的任務,造成了過多的資源消耗,當 map-reduce job 非常多的時候,會造成很大的記憶體開銷,潛在來說,也增加了 JobTracker fail 的風險,這也是業界普遍總結出老 Hadoop 的 Map-Reduce 只能支援 4000 節點主機的上限。
  3. 在 TaskTracker 端,以 map/reduce task 的數目作為資源的表示過於簡單,沒有考慮到 cpu/ 記憶體的佔用情況,如果兩個大記憶體消耗的 task 被排程到了一塊,很容易出現 OOM。
  4. 在 TaskTracker 端,把資源強制劃分為 map task slot 和 reduce task slot, 如果當系統中只有 map task 或者只有 reduce task 的時候,會造成資源的浪。
  5. 原始碼層面分析的時候,會發現程式碼非常的難讀,常常因為一個 class 做了太多的事情,程式碼量達 3000 多行,,造成 class 的任務不清晰,增加 bug 修復和版本維護的難度。
  6. 從操作的角度來看,現在的 Hadoop MapReduce 框架在有任何重要的或者不重要的變化 ( 例如 bug 修復,效能提升和特性化 ) 時,都會強制進行系統級別的升級更新。更糟的是,它不管使用者的喜好,強制讓分散式叢集系統的每一個使用者端同時更新。這些更新會讓使用者為了驗證他們之前的應用程式是不是適用新的 Hadoop 版本而浪費大量時間。

MapReduce 2.x/Yarn框架

從業界使用分散式系統的變化趨勢和 hadoop 框架的長遠發展來看,MapReduce 的 JobTracker/TaskTracker 機制需要大規模的調整來修復它在可擴充套件性,記憶體消耗,執行緒模型,可靠性和效能上的缺陷。在過去的幾年中,hadoop 開發團隊做了一些 bug 的修復,但是最近這些修復的成本越來越高,這表明對原框架做出改變的難度越來越大。

YARN是Hadoop 2.0中的資源管理系統,它的基本設計思想是將MRv1中的JobTracker拆分成了兩個獨立的服務:一個全域性的資源管理器ResourceManager和每個應用程式特有的ApplicationMaster。其中ResourceManager負責整個系統的資源管理和分配,而ApplicationMaster負責單個應用程式的管理。ApplicationMaster 承擔了以前的 TaskTracker 的一些角色,ResourceManager 承擔了 JobTracker 的角色。

YARN是一個資源管理、任務排程的框架,主要包含三大模組:ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)。其中,ResourceManager負責所有資源的監控、分配和管理;ApplicationMaster負責每一個具體應用程式的排程和協調;NodeManager負責每一個節點的維護。對於所有的applications,RM擁有絕對的控制權和對資源的分配權。而每個AM則會和RM協商資源,同時和NodeManager通訊來執行和監控task。 幾個模組之間的關係如圖所示。

Hadoop學習(二)——MapReduce\Yarn架構

MapReduce 2.x重點概念

ResourceManager(RM)

RM是一個全域性的資源管理器,負責整個系統的資源管理和分配。它主要由兩個元件構成:排程器(Scheduler)應用程式管理器(Applications Manager,AsM)

  • 排程器

    排程器根據容量、佇列等限制條件(如每個佇列分配一定的資源,最多執行一定數量的作業等),將系統中的資源分配給各個正在執行的應用程式。

    需要注意的是,該排程器是一個“純排程器”,它不再從事任何與具體應用程式相關的工作,比如不負責監控或者跟蹤應用的執行狀態等,也不負責重新啟動因應用執行失敗或者硬體故障而產生的失敗任務,這些均交由應用程式相關的ApplicationMaster完成。排程器僅根據各個應用程式的資源需求進行資源分配,而資源分配單位用一個抽象概念“資源容器”(Resource Container,簡稱Container)表示,Container是一個動態資源分配單位,它將記憶體、CPU、磁碟、網路等資源封裝在一起,從而限定每個任務使用的資源量。此外,該排程器是一個可插拔的元件,使用者可根據自己的需要設計新的排程器,YARN提供了多種直接可用的排程器,比如Fair Scheduler和Capacity Scheduler等。

  • 應用程式管理器

    應用程式管理器負責管理整個系統中所有應用程式,包括應用程式提交、與排程器協商資源以啟動ApplicationMaster、監控ApplicationMaster執行狀態並在失敗時重新啟動它等。

NodeManager(NM)

NM是每個節點上的資源和工作管理員,一方面,它會定時地向RM彙報本節點上的資源使用情況和各個Container的執行狀態;另一方面,它接收並處理來自AM的Container啟動/停止等各種請求。

ApplicationMaster(AM)

使用者提交的應用程式均包含一個AM,負責為應用程式申請資源並分配給內部的任務,應用的監控,跟蹤應用執行狀態,重啟失敗任務等。ApplicationMaster是應用框架,它負責向ResourceManager協調資源,並且與NodeManager協同工作完成Task的執行和監控。MapReduce就是原生支援的一種框架,可以在YARN上執行Mapreduce作業。有很多分散式應用都開發了對應的應用程式框架,用於在YARN上執行任務,例如Spark,Storm等。如果需要,我們也可以自己寫一個符合規範的YARN application。

Container

Container 是 YARN 中的資源抽象,它封裝了某個節點上的多維度資源,如記憶體、CPU、磁碟、網路等,當AM向RM申請資源時,RM為AM返回的資源便是用Container表示的。YARN會為每個任務分配一個Container,且該任務只能使用該Container中描述的資源。每個Container可以根據需要執行ApplicationMaster、Map、Reduce或者任意的程式。

YARN應用工作流程

Hadoop學習(二)——MapReduce\Yarn架構

  1. 使用者向YARN中提交應用程式,其中包括AM程式、啟動AM的命令、命令引數、使用者程式等;事實上,需要準確描述執行ApplicationMaster的unix程式的所有資訊。提交工作通常由YarnClient來完成。

  2. RM為該應用程式分配第一個Container,並與對應的NM通訊,要求它在這個Container中啟動AM;

  3. AM首先向RM註冊,這樣使用者可以直接通過RM査看應用程式的執行狀態,執行狀態通過 AMRMClientAsync.CallbackHandler的getProgress() 方法來傳遞給RM。 然後它將為各個任務申請資源,並監控它的執行狀態,直到執行結束,即重複步驟4〜7;

  4. AM採用輪詢的方式通過RPC協議向RM申請和領取資源;資源的協調通過 AMRMClientAsync非同步完成,相應的處理方法封裝在AMRMClientAsync.CallbackHandler中。

  5. —旦AM申請到資源後,便與對應的NM通訊,要求它啟動任務;通常需要指定一個ContainerLaunchContext,提供Container啟動時需要的資訊。

  6. NM為任務設定好執行環境(包括環境變數、JAR包、二進位制程式等)後,將任務啟動命令寫到一個指令碼中,並通過執行該指令碼啟動任務;

  7. 各個任務通過某個RPC協議向AM彙報自己的狀態和進度,以讓AM隨時掌握各個任務的執行狀態,從而可以在任務失敗時重新啟動任務;ApplicationMaster與NM的通訊通過NMClientAsync object來完成,容器的所有事件通過NMClientAsync.CallbackHandler來處理。例如啟動、狀態更新、停止等。

  8. 應用程式執行完成後,AM向RM登出並關閉自己。

相關文章