1. 程式人生 > >Hadoop—關於YARN

Hadoop—關於YARN

Apache YARN(Yet Another Resource Negotiator)是Hadoop的叢集資源管理系統。YARN被引入Hadoop 2,最初是為了改善MapReduce的實現,但它具有足夠的通用性,同樣可以支援其他的分散式計算模式。
  YARN提供請求和使用叢集資源的API,但這些API很少直接用於使用者程式碼。相反,使用者程式碼中用的是分散式計算框架提供的更高層的API,這些API建立在YARN之上且向用戶隱藏了資源管理細節。
  這裡寫圖片描述
  一些分散式計算框架(MapReduce、Spark等)作為YARN應用執行在叢集計算層(YARN)和叢集儲存層(HDFS和HBase)上。
  還有一層應用是建立在圖4-1所示的框架之上。如pig,hive和Crunch都是執行在MapReduce,Spark或Tez(或三個都可)之上的處理框架,它們不和YARN直接打交道。

剖析YARN應用執行機制

YARN通過兩類長期執行的守護程序(Daemon)提供自己的核心服務:管理叢集上資源使用的資源管理器(resource manager)、執行在叢集中所有節點上且能夠啟動和監控容器(container)的節點管理器(node manager)。容器用於執行特定應用程式的程序,每個容器都有資源限制(記憶體、CPU等)。一個容器可以是一個Unix程序,也可以是一個Linux cgroup,這取決於YARN的配置。
  YARN執行
  上圖表示了YARN是如何執行一個應用的。為了在YARN上執行一個應用,首先,客戶端聯絡資源管理器,要求它執行一個application master程序(步驟1)。然後資源管理器找到一個能夠在容器中啟動application master的節點管理器(步驟2a和2b)。準確的說,application mast一旦執行起來後能做些什麼依賴於應用本身。有可能是在所處的容器中簡單地執行一個計算,並將結果返回給客戶端;或是想資源管理器請求更多的容器(步驟3),以用於執行一個分散式計算(步驟4a和4b)。後者是MapReduce YARN應用所做的事情。
  注意,YARN本身不會為應用的各部分(客戶端、master和程序)彼此間通訊提供任何手段。大多數重要的YARN應用使用某種形式的遠端通訊機制(例如Hadoop的RPC層)來向客戶端傳遞狀態更新和返回結果,但是這些通訊機制都是專屬於各應用的。

資源請求

YARN有一個靈活的資源請求模型。當請求多個容器時,可以指定每個容器需要的計算資源數量(記憶體和CPU),還可以指定對容器的本地限制要求。
  本地化對於確保分散式資料處理演算法高效實用叢集頻寬非常重要,因此,YARN允許一個應用為所申請的容器指定本地限制。本地限制可用於申請位於指定節點或機架,或叢集中任何位置(機架外)的容器。
  有時本地限制無法被滿足,這種情況下要麼不分配資源,或者可選擇放鬆限制。例如,一個節點由於已經運行了別的容器而無法再啟動新的容器,這時如果有應用請求該節點,則YARN將嘗試在同一機架中的其他節點上啟動一個容器,如果還不行,則會嘗試叢集中的任何一個節點。
  通常情況下,當啟動一個容器用於處理HDFS資料塊(為了在MapReduce中執行一個map任務)時,應用將會向這樣的節點申請容器:儲存該資料塊三個複本的節點,或是儲存這些複本的機架中的一個節點。如果都申請失敗,則申請叢集中的任意節點。
  YARN應用可以在執行中的任意時刻提出資源申請。例如,可以在最開始提出所有的請求,或者為了滿足不斷變化的應用需求,採取更為動態的方式在需要更多資源時提出請求。
  Spark採用了上述第一種方式,在叢集上啟動固定數量的執行器。另一方面,MapReduce則分兩步走,在最開始時申請map任務容器,reduce任務容器的啟用則放在後期。同樣,如果任何任務出現失敗,將會另外申請容器以重新執行失敗的任務。

應用生命期

YARN應用的生命期差異性很大:有幾秒的短期應用,也有連續執行幾天甚至幾個月的長期應用。與其關注應用執行多長時間,不如按照應用到使用者作業的作業之間的對映關係對應用進行分類更有意義。最簡單是模型是一個使用者作業對應一個應用,這也是MapReduce採取的方式。
  第二種模型是,作業的每個工作流或每個使用者對話(可能並無關聯性)對應一個應用。這種方法要比第一種情況效率更高,因為容器可以在作業之間重用,並且有可能快取作業之間的中間資料。Spark採取的是這種模型。
  第三種模型是,多個使用者共享一個長期執行的應用。這種應用通常是作為一種協調者的角色在執行。例如,Apache Slider有一個長期執行的application master,主要用於啟動叢集上的其他應用。Impala也使用這種模型提供了一個代理應用,Impala守護程序通過該代理請求叢集資源。由於避免了啟動新application master帶來的開銷,一個總是開啟的application master意味著使用者將獲得非常低延遲的查詢響應。

YARN與MapReduce 1相比

有時用“MapReduce 1”來指代Hadoop初識版本(版本1及更早期版本)中的MapReduce分散式執行框架,以區別於使用YARN(Hadoop 2及以後的版本)的MapReduce 2。
  MapReduce 1中,有兩類守護程序控制著作業執行過程:一個jobtracker及一個或多個tasktracker。jobtracker通過排程tasktracker上執行的任務來協調所有執行在系統上的作業。tasktracker在執行任務的同時將執行進度報告發送給jobtracker,jobtracker由此記錄每項作業任務的整體進度情況。如果其中一個任務失敗,jobtracker可以在另一個tasktracker節點上重新排程該任務。
  MapReduce 1中,jobtracker同時負責作業排程(將該任務與tasktracker匹配)和任務進度監控(跟蹤任務、重啟失敗或遲緩的任務;記錄任務流水,如維護計數器的計數)。相比之下,YARN中,這些職責是由不同的實體擔負的:它們分別是資源管理器和application master(每個MapReduce作業一個)。jobtracker也負責儲存已完成作業的作業歷史,但是也可以執行一個作業歷史伺服器作為一個獨立的守護程序來取代jobtracker。在YARN中,與之等價的角色是時間軸伺服器,它主要用於儲存應用歷史。
  YARN中與tasktracker等價的角色是節點管理器。下圖為MapReduce 1和YARN中的對映關係。
  這裡寫圖片描述
  YARN的很多設計是為了解決MapReduce 1的侷限性,使用YARN的好處包括以下幾個方面:

  • 列擴充套件性(Scalability)
      與MapReduce 1相比,YARN可以在更大規模的叢集上執行。當節點數達到4000,任務數達到40000時,MapReduce 1會遇到可擴充套件性瓶頸,瓶頸源自於jobtracker必須同時管理作業和任務這樣一個事實。YARN利用其資源管理器和application master分離的架構優點克服了這個侷限性,可以擴充套件到面向將近10000個結點和100000個任務。
      與jobtracker相比,一個應用的每個例項(這裡指一個MapReduce作業)都對應一個專門的application master,該管理程序在(master)在應用的持續期間執行。這個模型實際上與初始的Google MapReduce論文中所描述的更接近。論文中描述瞭如何啟動一個管理(master)程序以協調執行在一系列工作(worker)上的map和reduce任務。
  • 可用性(Availability)
      當服務守護程序失敗時,通過為另一個守護程序複製接管工作所需的狀態以便其繼續提供服務,從而可以獲得高可用性(HA,High availability)。然而,jobtracker記憶體中大量快速變化的複雜狀態(例如,每個任務狀態每幾秒會更新一次)使得改進jobtracker服務獲得高可用性非常困難。
      由於YARN中jobtracker在資源管理器和application master之間進行了職責劃分,高可用的服務隨之成為一個分而治之的問題:先為資源管理器提供高可用性,再為YARN應用(針對每個應用)提供高可用性。實際上,對於資源管理器和application master,Hadoop 2都支援MapReduce作業的高可用性。
  • 利用率
      MapReduce 1中,每個tasktracker都配置有若干固定長度的slot,這些slot是靜態分配的,在配置的時候就被劃分為map slot和reduce slot。一個map slot僅能用於執行一個map任務;一個reduce slot僅能用於執行一個reduce任務。
      YARN中,一個節點管理器管理一個資源池,而不是指定的固定數目的slot。YARN上執行的MapReduce不會出現由於叢集中僅有map slot可用導致reduce任務必須等待的情況,而MapReduce 1則會有這樣的問題,如果能夠獲得執行任務的資源,那麼應用就會正常執行。
      更進一步,YARN中的資源是精細化管理的,這樣一個應用能夠按需請求資源,而不是請求一個不可分割的、對於特定的任務而言可能會太大(浪費資源)或太小(可能會導致失敗)的slot。
  • 多租戶
      在某種程度上,可以說YARN的最大優點在於向MapReduce以外的其他型別的分散式應用開放了Hadoop。MapReduce僅僅是許多YARN應用中的一個。
      使用者甚至可以在同一個YARN叢集上執行不同版本的MapReduce,這使得升級MapReduce的過程更好管理。(注意,MapReduce的一些部件,例如作業歷史服務和shuffle控制代碼,和YARN自身一樣,仍然需要在叢集範圍內升級。)

YARN中的排程

理想情況下,YARN應用發出的資源請求應該立刻給予滿足,然而現實中資源是有限的,在一個繁忙的叢集上,一個應用經常需要等待才能得到所需的資源。YARN排程器的工作就是根據既定策略為應用分配資源。排程通常是一個難題,並且沒有一個所謂“最好”的策略,這也是為什麼YARN提供了多種排程器和可配置策略供我們選擇的原因。

排程選項

YARN中有三種排程器可用:FIFO排程器(FIFO Scheduler),容量排程器(Capacity Scheduler)和公平排程器(Fair Scheduler)。FIFO排程器將應用放置在一個佇列中,然後按照提交的順序(先進先出)執行應用。首先為佇列中第一個應用的請求分配資源,第一個應用的請求被滿足後再依次為佇列中下一個應用服務。
  FIFO排程器的優點:簡單易懂,不需要任何配置,但是不合適共享叢集。大的應用會佔用叢集中的所有資源,所有每個應用必須等待直到輪到自己執行。在一個共享叢集中,更適合使用容量排程器或公平排程器。這兩種排程器都允許長時間執行的作業能及時完成,同時也允許正在進行較小臨時查詢的使用者能夠在合理時間內得到返回結果。
  使用容量排程器是,一個獨立的專門佇列保證小作業一提交就可以啟動,由於佇列容量是為那個佇列中的作業所保留的,因此這種策略是以整個叢集的利用率為代價的。這意味著與使用FIFO排程器相比,大作業執行的時間要長。
  使用公平排程器時,不需要預留一定量的資源,因為排程器會在所有執行的作業之間動態平衡資源。這個大作業啟動時,它也是唯一執行的作業,因而獲得叢集中所有的資源。當第二個小作業啟動時,它被分配到叢集的一半資源,這樣每個作業都能公平共享資源。
  注意,從第二個作業的啟動到獲得公平共享資源之間會有時間滯後,因為它必須等待第一個作業使用的容器用完並釋放資源。當小作業結束且不再申請資源後,大作業將回去再次使用全部的叢集資源。最終的效果是:既得到了較高的叢集利用率,又能保證小作業能及時完成。

容量排程器配置

容量排程器允許多個組織共享一個Hadoop叢集,每個組織可以分配到全部叢集資源的一部分。每個組織被配置一個專門的的佇列,每個佇列被配置為可以使用一定的叢集資源。佇列可以進一步按層次劃分,這樣每個組織內的不同使用者能夠共享該組織佇列所分配的資源。在一個佇列內,使用FIFO排程器策略對應用進行排程。
  單個作業使用的資源不會超過其佇列容量。然而,如果佇列中有多個作業,並且佇列資源不夠用了呢?這時如果仍有可用的空閒資源,那麼容量排程器會將空餘的資源分配給佇列中的作業,哪怕這會超出佇列容量。這稱為“彈性佇列”。
  正常操作時,容器排程器不會通過強行中止來搶佔容器(container)。因此,如果一個佇列一開始資源夠用,然後隨著需求增長,資源開始不夠用時,那麼這個佇列就只能等著其他佇列釋放容器資源。緩解這種情況的方法是,為佇列設定一個最大容量限制,這樣這個佇列就不會過多侵佔其他佇列的容量了。當然,這樣做是以犧牲佇列彈性為代價的,因此需要在不斷嘗試和失敗中找到一個合理的折中。

佇列放置

將應用放置在哪個佇列中,取決於應用本身,例如,在MapReduce中,可以通過設定屬性mapreduce.job.queuename來指定要用的佇列。如果佇列不存在,則在提交時會發送錯誤。如果不指定佇列,那麼應用將被放在一個名為“default”的預設佇列中。

公平排程器配置

公平排程器旨在為所有執行的應用公平分配資源。想象兩個使用者A和B,分別擁有自己的佇列,A啟動一個作業,在B沒有需求時分配到全部可用資源;當A的作業仍在執行時B啟動一個作業,一段時間後,按照我們先看到的方式,每個作業都用到一半的叢集資源。這時,如果B啟動第二個作業且其他作業仍在執行,那麼第二個作業將和B的其他作業共享資源,因此B的每個作業將佔用四分之一的叢集資源,而A仍然繼續佔用一半的叢集資源,最終的結果就是資源在使用者之間實現了公平共享。
  1、啟動公平排程器
  公平排程器的使用由屬性yarn.resourcemanager.scheduler.class的設定所決定。預設是使用容量排程器(CDH中是預設使用公平排程器),如果要使用公平排程器,需要將yarn.site.xml檔案中的yarn.resourcemanager.scheduler.class設定為公平排程器的完全限定名:org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
  2、佇列配置
  通過一個名為fair-scheduler.xml的分配檔案對公平排程器進行配置,該檔案位於類路徑下。(可以通過設定屬性yarn.scheduler.fair.allocation.file來修改檔名)。當沒有該分配檔案時,公平排程器的工作策略同先前所描述一樣:每個應用放置在一個以使用者名稱命名的佇列中,佇列是在使用者提交第一個應用時動態建立的。
  通過分配檔案可以為每個佇列進行配置。這樣可以對容量排程器支援的層次佇列進行配置。
  每個佇列可以有不同的排程策略。佇列的預設排程策略可以通過頂層元素defaultQueueSchedulingPolicy進行設定,如果省略,預設使用公平排程。儘管名稱是“公平”,公平排程器也支援佇列級別的FIFO策略,以及Dominant Resource Fairness(drf)策略。
  佇列的排程策略可以被該佇列的schedulingPolicy元素指定的策略覆蓋。
  3、佇列配置
  公平排程器使用一個基於規則的系統來確定應用應該放在哪個佇列。
  4、搶佔
  在一個繁忙的叢集中,當作業被提交給一個空佇列時,作業不會立刻啟動,直到叢集上已經執行的作業釋放了資源。為了使作業從提交到執行所需的時間可預測,公平排程器支援“搶佔”功能。
  所謂搶佔,就是允許排程器終止那些佔用資源超過了其公平共享份額的佇列的容器,這些容器資源釋放後可以分配給資源數量低於應得份額的佇列。注意,搶佔會降低整個叢集的效率,因為被終止的container需要重新執行。
  通過將yarn.scheduler.fair.preemption設定為true,可以全面啟用搶佔功能。有兩個相關的搶佔超時設定,一個用於最小共享(minimum share preemption timeout),另一個用於公平共享(fair share preemption timeout),兩者設定時間均為秒級。預設情況下,兩個超時引數均不設定。所有為了允許搶佔容器,需要至少設定其中一個超時引數。
  如果佇列在最小共享指定的時間內未獲得被承諾的最小共享資源,排程器就會搶佔其他容器。可以通過分配檔案中的頂層元素defaultMinSharePreemptionTimeout為所有佇列設定預設的超時時間,還可以通過設定每個佇列的minSharePreemptionTimeout元素來為單個佇列指定超時時間。
  如果佇列在公平共享指定的時間內未獲得的資源仍然低於其公平共享份額的一半,那麼排程器就會搶佔其他容器。可以通過分配檔案中的頂層元素defaultFairSharePreemptionTimeout為所有佇列設定預設的超時時間,還可以通過設定每個佇列的fairSharePreemptionTimeout元素來為單個佇列指定超時時間。通過設定defaultFairSharePreemptionThreshold和fairSharePreemptionThreshold(針對每個佇列)可以修改超時閾值,預設值是0.5。

延遲排程

所有的YARN排程器都試圖以本地請求為重。在一個繁忙的叢集上,如果一個應用請求某個節點,那麼極有可能此時有其他容器正在該節點上執行,顯而易見的處理是,like放款本地性需求,在同一機架上分配一個容器,然而,通過實踐發現,此時如果等待一小段實踐(不超過幾秒),能夠戲劇性的增加在所請求的節點上分配到一個容器的機會,從而可以提高叢集的效率。這個特性稱之為延遲排程(delay scheduling)。容量排程器和公平排程器都支援延遲排程。
  YARN中的每個節點管理器週期性的(預設每秒一次)向資源管理器傳送心跳請求。心跳中攜帶了節點管理器中正執行的容器、新容器可用的資源等資訊,這樣對於一個計劃執行一個容器排程應用而言,每個心跳就是一個潛在的排程機會(scheduling opportunity)。
  當使用延遲排程器,可以通過設定yarn.scheduler.capacity.node-locality-delay來配置延遲排程。設定為正數,表示排程器在放鬆節點限制、改為匹配同一機架上的其他節點前,準備錯過的排程機會的數量。
  公平排程器也使用排程機會的數量來決定延遲時間,儘管是使用叢集規模的比例來表示這個值,例如將yarn.sheduler.fair.locality.threshold.node設定為0.5,表示排程器在接收同一機架上的其他節點前,將一直等待指導叢集中的一半節點都已經給過排程機會。還有相關的屬性yarn.sheduler.fair.locality.threhold.rack,表示在接收另一個機架替代所申請的機架之前需要等待的時長閾值。

主導資源公平性

對於單一型別資源,如記憶體的排程,容量或公平性的概念很容易確定。如果兩個使用者正在執行應用,可以通過度量每個應用使用的記憶體來比較兩個應用。當有多重資源型別需要排程時,事情就會變得複雜。例如,如果一個使用者的應用對CPU的需求量很大,但對記憶體的需求量很少;而另一個使用者的應用需要很少的CPU,但對記憶體需求量很大,那麼如何比較這兩個應用呢?
  YARN中排程器解決這個問題的思路是,觀察每個使用者的主導資源,並將其作為對叢集資源使用的一個度量,這個方法稱為“主導資源公平性”(Dominant Resource Fairness,DRF)。這個思想用一個簡單的例子就可以很好的給予解釋。
  想象一個總共100個CPU和10TB的叢集。應用A請求的每份容器資源為2個CPU和300G記憶體,用用B請求的每份容器資源為6個CPU和100G記憶體。A請求的資源在叢集資源中佔比分別為2%和3%,由於記憶體佔比(3%)大於CPU佔比(2%),所有記憶體是A的主導資源。B請求的資源在叢集資源中佔比分別為6%和1%,所有CPU是B的主導資源。由於B申請的資源是A的兩倍(6%vs3%),所以在公平排程下,B將分到一半的容器數。
  預設情況下不用DRF,因此在資源計算期間,只需要考慮記憶體,不必考慮CPU。對容器排程器進行配置後,可以使用DRF,將capacity-scheduler.xml檔案中的org.apache.hadoop.yarn.util.resource.DominantResourceCalculator設為yarn.scheduler.capacity.resource-calculator即可。
  公平排程器若要使用DRF,通過將分配檔案中的頂層元素defaultQueueSchudulingPolicy設為drf即可。