YARN 是Hadoop新版中的資源控制框架。本文旨在深入剖析ResourceManager的調度器,探討三種調度器的設計側重,最后給出一些配置建議和參數解釋。 本文分析基于CDH4.2.1。調度器這個部分目前還在快速變化之中。例如,CPU資源分配等特性在不就的將來就會加入。
YARN是Hadoop新版中的資源控制框架。本文旨在深入剖析ResourceManager的調度器,探討三種調度器的設計側重,最后給出一些配置建議和參數解釋。
本文分析基于CDH4.2.1。調度器這個部分目前還在快速變化之中。例如,CPU資源分配等特性在不就的將來就會加入。
為了方便查閱源代碼,原代碼位置使用[類名:行號]方式表示。
名詞解釋:
ResourceManager:以下簡稱RM。YARN的中控模塊,負責統一規劃資源的使用。
NodeManager:以下簡稱NM。YARN的資源結點模塊,負責啟動管理container。
ApplicationMaster:以下簡稱AM。YARN中每個應用都會啟動一個AM,負責向RM申請資源,請求NM啟動container,并告訴container做什么事情。
Container:資源容器。YARN中所有的應用都是在container之上運行的。AM也是在container上運行的,不過AM的container是RM申請的。
1.RM中的調度器
ResourceManager是YARN資源控制框架的中心模塊,負責集群中所有的資源的統一管理和分配。它接收來自NM的匯報,建立AM,并將資源派送給AM。整體的RM的框架可以參考:RM總體架構
?
最初的hadoop的版本只有FifoScheduler(先進先出調度器)。當Hadoop集群在大規模使用的時候,如何整合資源和分配資源就是一個迫切的需求。對此,Yahoo!和facebook先后開發了CapacityScheduler(容量調度器)和FairScheduler(公平調度器)。在新版本中,這兩個調度器在保持核心算法的基礎上,也被重新開發了一次。(實際上所有整個YARN的代碼都是重寫的…)
2.調度器的接口
首先來了解一下調度器的工作方式和對外暴露的接口:[ResourceScheduler:36]
一個完整的調度器在內存中都會維護一個隊列,應用,NM,Container的關系。同時,一個調度器也是一個事件處理器,通過RM的異步的事件調用機制知曉外部的發生的事情。要跟外部交互也要發送相應的事件。調度器一共要處理6個調度事件。
事件 | 發送時機 | 處理邏輯 |
---|---|---|
NODE_ADDED | 一個NM被添加 | 增加總資源池的大小,修改內存狀態。 |
NODE_REMOVED | 一個NM被移除 | 刪除一個NM,減少總資源池的大小,回收內存狀態中在這個NM上的Container,對每個container發送KILL事件。 |
NODE_UPDATE | 一個NM跟RM進行心跳 |
調度器會根據當前的NM狀況,在這個NM上為某一個AM分配Container,并記錄這個Container的信息,留待AM獲取。這個部分是調度器真正分配container的部分。后面會重點描述。 |
APP_ADDED | 一個新的應用被提交 | 如果接受應用,發送APP_ACCEPTED事件,否則發送APP_REJECTED事件。 |
APP_REMOVED | 一個應用移除 | 可能是正常或者被殺死。清除內存中這個應用的所有的container,對每個container發送KILL事件。 |
CONTAINER_EXPIRED | 一個container過期未被使用 | 修改內存中這個contianer相關的內存狀態。 |
除了這6個事件,還有一個函數會在AM跟RM心跳的時候會被調用。[YARNScheduler:105]
Allocation allocate(ApplicationAttemptId appAttemptId,List
AM會告訴調度器一些資源申請的請求和已經使用完的container的列表,然后獲取到已經在NODE_UPDATE分配給這個應用的container的分配。
可以看到調度器接受資源的申請和分配資源這個動作是異步的。
3.資源分配模型?
無論FifoScheduler,CapacityScheduler和FairScheduler的核心資源分配模型都是一樣的。
調度器維護一群隊列的信息。用戶可以向一個或者多個隊列提交應用。每次NM心跳的時候,調度器,根據一定的規則選擇一個隊列,再在隊列上選擇一個應用,嘗試在這個應用上分配資源。不過,因為一些參數限制了分配失敗,就會繼續選擇下一個應用。在選擇了一個應用之后,這個應用對應也會有很多的資源申請的請求。調度器會優先匹配本地資源是申請請求,其次是同機架的,最后的任意機器的。
總的來說,3種調度器就是在回答如何選擇一個隊列,在一個隊列上如何選擇一個應用的問題。
當然,實際上,比起簡單的FifoScheduler。CapacityScheduler和FairScheduler還有更多新奇好玩的特性。
4.調度器比較
我們先比較下3種調度器。
調度器 | FifoScheduler | CapacityScheduler | FairScheduler |
---|---|---|---|
設計目的 | 最簡單的調度器,易于理解和上手 |
多用戶的情況下,最大化集群的吞吐和利用率 |
多用戶的情況下,強調用戶公平地貢獻資源 |
隊列組織方式 | 單隊列 | 樹狀組織隊列。無論父隊列還是子隊列都會有資源參數限制,子隊列的資源限制計算是基于父隊列的。應用提交到葉子隊列。 | 樹狀組織隊列。但是父隊列和子隊列沒有參數繼承關系。父隊列的資源限制對子隊列沒有影響。應用提交到葉子隊列。 |
資源限制 | 無 | 父子隊列之間有容量關系。每個隊列限制了資源使用量,全局最大資源使用量,最大活躍應用數量等。 | 每個葉子隊列有最小共享量,最大資源量和最大活躍應用數量。用戶有最大活躍應用數量的全局配置。 |
隊列ACL限制 | 可以限制應用提交權限 | 可以限制應用提交權限和隊列開關權限,父子隊列間的ACL會繼承。 | 可以限制應用提交權限,父子隊列間的ACL會繼承。但是由于支持客戶端動態創建隊列,需要限制默認隊列的應用數量。目前,還看不到關閉動態創建隊列的選項。 |
隊列排序算法 | 無 | 按照隊列的資源使用量最小的優先 | 根據公平排序算法排序 |
應用選擇算法 | 先進先出 | 先進先出 | 先進先出或者公平排序算法 |
本地優先分配 | 支持 | 支持 | 支持 |
延遲調度 | 不支持 | 不支持 | 支持 |
資源搶占 | 不支持 | 不支持 | 支持,看到代碼中也有實現。但是,由于本特性還在開發階段,本文沒有真實試驗。 |
簡單總結下:
FifoScheduler:最簡單的調度器,按照先進先出的方式處理應用。只有一個隊列可提交應用,所有用戶提交到這個隊列。可以針對這個隊列設置ACL。沒有應用優先級可以配置。
CapacityScheduler:可以看作是FifoScheduler的多隊列版本。每個隊列可以限制資源使用量。但是,隊列間的資源分配以使用量作排列依據,使得容量小的隊列有競爭優勢。集群整體吞吐較大。延遲調度機制使得應用可以放棄,夸機器或者夸機架的調度機會,爭取本地調度。
FairScheduler:多隊列,多用戶共享資源。特有的客戶端創建隊列的特性,使得權限控制不太完美。根據隊列設定的最小共享量或者權重等參數,按比例共享資源。延遲調度機制跟CapacityScheduler的目的類似,但是實現方式稍有不同。資源搶占特性,是指調度器能夠依據公平資源共享算法,計算每個隊列應得的資源,將超額資源的隊列的部分容器釋放掉的特性。
5.本地優化與延遲調度
我們解釋一下什么是本地優化和延遲調度。
Hadoop是構建在以hdfs為基礎的文件系統之上的。YARN所運行的應用的絕大部分輸入都是hdfs上的文件。而hdfs上的文件的是分塊多副本存儲的。假設文件系統的備份因子是3。則每一個文件塊都會在3個機器上有副本。在YARN運行應用的時候,AM會將輸入文件進行切割,然后,AM向RM申請的container來運行task來處理這些被切割的文件段。
假如輸入文件在ABC三個機器上有備份,那如果AM申請到的container在這3個機器上的其中一個,那這個task就無須從其它機器上傳輸要處理的文件段,節省網絡傳輸。這就是Hadoop的本地優化。所以Hadoop的文件備份數量除了和數據安全有關,還對應用運行效率有莫大關系。
YARN的實現本地優化的方式是AM給RM提交的資源申請的時候,會同時發送本地申請,機架申請和任意申請。然后,RM的匹配這些資源申請的時候,會先匹配本地申請,再匹配機架申請,最后才匹配任意申請。關于AM資源申請機制可以參考:ContainerAlloctor分析
而延遲調度機制,就是調度器在匹配本地申請失敗的時候,匹配機架申請或者任意申請成功的時候,允許略過這次的資源分配,直到達到延遲調度次數上限。CapacityScheduler和FairScheduler在延遲調度上的實現稍有不同,前者的調度次數是根據規則計算的,后者的調度次數通過配置指定的,但實際的含義是一樣的。
6.參數配置
要徹底理解各個參數配置中關系,就不能忽略掉調度器的調度算法和調度細節。
以下是和調度器密切相關的集群配置
配置文件 |
配置項 |
值 |
含義 |
---|---|---|---|
mapred-site.xml |
yarn.app.mapreduce.am.resource.mb |
1024 |
ApplicationMaster的container占用的內存大小 |
mapreduce.map.memory.mb mapreduce.reduce.memory.mb |
512/512 |
map/reduce階段申請的container的內存的大小 |
|
mapreduce.map.java.opts mapreduce.reduce.java.opts |
用戶設定的map/reduce階段申請的container的JVM參數。最大堆設定要比申請的內存少一些,用于JVM的非堆部分使用。 |
||
mapreduce.admin.map.child.java.opts mapreduce.admin.reduce.child.java.opts |
-Xmx500m |
管理員設定的map/reduce階段申請的container的默認JVM啟動參數。啟動container的命令行會先連接管理員設定參數,然后再連接用戶設定參數。 |
|
yarn-site.xml |
yarn.nodemanager.vmem-pmem-ratio |
4.0 |
container可使用的虛擬映射地址是物理內存的多少倍。 |
yarn.scheduler.minimum-allocation-mb |
512 |
container最小可申請的內存。在調度器中,很多資源計算部分會轉化為這個最小值的N倍進行計算。所以,設定可分配內存等資源的時候,最好是剛好為這個最小值的倍數。 |
|
yarn.scheduler.maximum-allocation-mb |
2048 |
container最多可申請的內存數量 |
|
yarn.resourcemanager.scheduler.class |
FairScheduler /CapacityScheduler |
ResourceManager加載的調度器類實例 |
|
yarn-site.private.xml |
yarn.nodemanager.resource.memory-mb |
4096 |
每個nodemanager可分配的內存總量 |
容量調度器(CapacityScheduler),由Yahoo!最初開發,被設計出來使得hadoop應用能夠被多用戶使用,且最大化整個集群資源的吞吐量。
在hadoop集群配置中啟動容量調度器之后,調度器會從classpath中加載capacity-scheduler.xml文件,完成容量調度器的初始化??偨Y起來有如下特性:
1) 動態更新配置:容量調度器的配置文件在運行時可以隨時重新加載來調整分配參數。除非重啟ResourceManager,否則隊列只能添加不能刪除,但是允許關閉。修改配置文件后,使用以下命令可以刷新配置。
yarn rmadmin -refreshQueues?
2) 樹形組織隊列:容量調度器的隊列是按照樹形結構組織的。根隊列只有一個root隊列。子隊列分享父隊列的資源。每個隊列設定一個容量值代表可使用父隊列的容量值,容量值會影響隊列的排序。父隊列的所有子隊列的容量相加一定是100,否則加載失敗。還有一個最大容量值表示子隊列絕對不會超過的使用上限。
3) 隊列應用限制:隊列可以設定最大提交的應用數量和AM占用資源的百分比。AM占用資源的百分比這個配置是用來計算隊列的最大活躍應用數量。這里有個小問題。調度器中最大活躍應用數量=AM占用資源的百分比*隊列最大可使用資源量/最小的container分配額度。但是我們在mapred-site.xml中會配置AM的內存額度會比最小container分配額度大,造成最大活躍應用數量虛高(可以理解,如果YARN加入不同的計算框架,AM的分配會不一致,所以這里使用最小container分配額度來計算。但是,如果是這樣的話,應該直接計算AM的內存使用量來控制)。
4) 用戶參數限制:用戶可以提交應用到多個隊列。不同隊列間用戶的應用運行情況,不相互影響。用戶在隊列中最大可占用資源受兩個參數控制,一個是單用戶占據隊列的百分比上限,一個是單用戶內存使用上限。具體參看下面的參數表。
5)資源分配選擇:不同隊列之間,按照隊列的資源使用比排序。同一隊列中的應用按照應用id排序,也就是先進先出。
6)延遲調度:當調度次數小于本地延遲調度次數的時候不接受機架調度。本地延遲調度次數,由yarn.scheduler.capacity.node-locality-delay配置,默認是-1,不開啟延遲調度。官方文檔中沒有提及這個參數。而任意調度的延遲調度上限是應用申請的機器的數量,不能配置。
?容量調度器通過各種的資源參數限制,來控制整體的資源分布。搞清楚容量調度器上的參數關系,也就基本理解了容量調度器了。
在RM的管理界面中,你會看到很多參數
?
?以下是容量調度器中的各種參數定義和計算關系:
隊列容量=yarn.scheduler.capacity..capacity/100 隊列絕對容量=父隊列的 隊列絕對容量*隊列容量? 隊列最大容量=yarn.scheduler.capacity..maximum-capacity/100? 隊列絕對最大容量=父隊列的 隊列絕對最大容量*隊列最大容量 絕對資源使用比=使用的資源/全局資源 資源使用比=使用的資源/(全局資源 * 隊列絕對容量)? 最小分配量=yarn.scheduler.minimum-allocation-mb 用戶上限=MAX(yarn.scheduler.capacity..minimum-user-limit-percent,1/隊列用戶數量) 用戶調整因子=yarn.scheduler.capacity..user-limit-factor? 最大提交應用=yarn.scheduler.capacity..maximum-applications? ?? ?如果小于0 設置為(yarn.scheduler.capacity.maximum-applications*隊列絕對容量) 單用戶最大提交應用=最大提交應用*(用戶上限/100)*用戶調整因子 AM資源占比(AM可占用隊列資源最大的百分比) ?? ?=yarn.scheduler.capacity..maximum-am-resource-percent ?? ?如果為空,設置為yarn.scheduler.capacity.maximum-am-resource-percent 最大活躍應用數量=全局總資源/最小分配量*AM資源占比*隊列絕對最大容量 單用戶最大活躍應用數量=(全局總資源/最小分配量*AM資源占比*隊列絕對容量)*用戶上限*用戶調整因子 本地延遲分配次數=yarn.scheduler.capacity.node-locality-delay
有了這個參數計算關系,就可以根據自己想要的形態配置對應的參數了。具體的參數配置實例這里就不累述了。
公平調度器(CapacityScheduler),由Facebook開發,被設計出來使得hadoop應用能夠被多用戶公平地共享整個集群資源的調度器。
在hadoop集群配置中啟動公平調度器之后,調度器會從classpath中加載fair-scheduler.xml和fair-allocation.xml文件,完成公平調度器的初始化。其中fair-scheduler.xml主要描述重要特性的配置,fair-allocation.xml主要描述了具體的隊列及其參數配置??偨Y起來有如下特性:
1) 動態更新配置:公平調度器的fair-allocation.xml配置文件在運行時可以隨時重新加載來調整分配參數。除非重啟ResourceManager,否則隊列只能添加不能刪除。修改fair-allocation.xml后,使用以下命令可以刷新配置。
yarn rmadmin -refreshQueues?
2) 樹形組織隊列:公平調度器的隊列是按照樹形結構組織的。根隊列只有一個root隊列。父子隊列除了ACL參數外,其余參數都不繼承。
3) 隊列應用參數:應用只能提交到葉子隊列。受隊列最大應用數量限制。隊列可以設定權重,最小共享量和最大使用量。權重和最小共享量將影響在公平排序算法中的排名,從而影響資源調度傾向。隊列還可以設定最大運行的應用數量。
4) 用戶參數限制:一個用戶可以提交應用到多個隊列。用戶受全局的最大可運行數量限制。
5) 資源分配選擇:資源分配的時候,使用公平排序算法選擇要調度的隊列,然后在隊列中使用先進先出算法或者公平排序算法選擇要調度的應用。
6) 延遲調度:每種資源申請的優先級都有一個資源等級標記。一開始標記都是NODE_LOCAL,只允許本地調度。如果調度機會大于NM數量乘以上界(locality.threshold.node),資源等級轉變為RACK_LOCAL、重置調度機會為0、接受機架調度。如果調度機會再次大于NM數量乘以上界(locality.threshold.rack),資源等級轉變為OFF_SWITCH、重置調度機會為0、接受任意調度。詳情代碼參看[FSSchedulerApp.getAllowedLocalityLevel:470]
7) 資源搶占:調度器會使用公平資源共享算法計算每個隊列應該得到的資源總量。如果一個隊列長時間得不到應得到的資源量,調度器可能會殺死占用掉該部分資源的容器。
這里簡要描述下fair-scheduler.xml中的配置項:
配置項 |
值 |
含義 |
---|---|---|
yarn.scheduler.fair.allocation.file |
本地路徑 |
allocation文件的路徑。 |
yarn.scheduler.fair.user-as-default-queue |
false |
在不指定提交隊列的名稱的情況下,是否使用用戶名字作為默認提交隊列。 |
yarn.scheduler.fair.preemption |
false |
是否開啟資源搶占特性。 |
yarn.scheduler.fair.sizebasedweight |
false |
是否將應用的輸入作為應用的排序權重。詳情參考公平排序算法。 |
yarn.scheduler.fair.assignmultiple |
false |
是否允許NodeManager一次分配多個容器。 |
yarn.scheduler.fair.max.assign |
1 |
如果允許多次分配,那最多可分配多少個容器。 |
locality.threshold.node |
0.7 |
調整從本地分配模式升級到機架分配模式需要的調度機會次數。配置值是調度次數和NodeManager的數量的百分比。跟集群中的備份因子相關。 |
locality.threshold.rack |
0.0 |
調整從機架分配模式升級到任意分配模式需要的調度機會次數。由于集群中沒有機架信息,所以設置0。 |
公平排序算法是公平調度器的核心算法。調度器在選取哪個隊列和隊列中的哪個應用需要優先得到資源調度的時候使用。每個隊列或者應用都有以下幾個供排序的參數:
1) 資源需求量。當前隊列或者應用希望獲得的資源的總量。
2) 最小共享量。隊列的最小共享量在配置中指定。應用的最小共享量為0。
3) 資源使用量。當前隊列或者應用分配到的總資源。
4) 權值。隊列的權重值在配置中指定。在開啟sizebasedweight特性的情況下,應用的權重=(log2(資源需求量))*優先級*調整因子。優先級當前都是1,。當應用運行超過5分鐘,調整因子為3。
排序算法的核心是兩個比較體的比較算法,具體如下:
1.計算比較體是否需要資源。即資源使用量是否小于資源需求量且小于最小共享量。 2.如果兩者都需要資源,計算資源分配比=資源使用量/Min(資源需求量,最小共享量)。資源分配比較小的優先。 3.如果一個需要,一個不需要,需要的優先。 4.如果兩者都不需要資源,計算使用權值比=資源使用量/權值。使用權值比較小的優先。 5.如果2或者4中的比較相同,則先提交的優先。
詳情代碼參看[SchedulingAlgorithms.FairShareComparator.compare:81]
公平調度器為公平地分配資源,在開啟資源搶占的特性的情況下,可能會殺死部分運行中的容器,釋放超額的資源。
公平調度器啟動的時候會建立一個UpdateThread的線程,負責計算公平資源量和進行資源搶占。其中,調度器使用了公平資源共享算法重新計算隊列的公平資源量。
名詞解釋:
資源權重比=資源獲得量/隊列權重。知道全局的資源權重比,每個隊列就可以根據自己的權值,知道自己能分配多少資源。
公平資源共享算法的目的是為了每個隊列公平地使用資源,這個公平體現在每個隊列得到的資源比等于他們的權值比。如果只是單純地求一個資源權重比,可以直接相除。但是由于需要滿足隊列的資源分配滿足最小共享量、最大資源量這些隊列上下界的限制,權值資源比不能直接計算。
反過來,如果知道資源權重比,就可以計算出集群一共需要多少資源,而且,集群資源需求量=Fun(資源權重比)是單調的。
所以可以使用二分資源權重比的方法,計算集群資源需求量,使得集群資源需求量逼近當前的集群資源量。
具體算法流程如下:
1.設置根隊列的公平資源量為全局資源總和 2.根隊列調用recomputeFairShares,計算公平資源量 2.1計算當前隊列的分配量=MIN(隊列總需求,公平資源量) 2.2計算資源權重比最大值。最大值=2^n,使得Fun(最大值)>集群資源量>Fun(最大值/2)。 2.2計算資源權重比。采用二分法計算,二分法次數最多25次。每個隊列的公平資源量= (權重*權重資源比,用最小共享量修正下界,用資源需求量修正上界) 2.3設置每個子隊列的公平資源量=資源權重比*權值。 2.4各個子隊列調用recomputeFairShares,遞歸計算。
詳情代碼參看[FairScheduler:221]
隊列的最小共享量越大,在集群繁忙的時候分配到的資源就越多。但是,如果每個用戶都將最小共享量設置到最大,不利于集群間的資源共享。建議,將隊列愿意共享出來的內存大小和隊列的權值掛鉤。含義就是,你愿意共享得越多,在整體資源分配中就越能分得更多的資源。
最后,我們再提一些重要的全局配置:
配置項 |
值 |
含義 |
---|---|---|
queueMaxAppsDefault |
0 |
自動創建的隊列的可提交應用為0,防止被而已提交應用。 |
userMaxAppsDefault |
100 |
用戶全局可運行應用 |
defaultQueueSchedulingMode |
fair |
隊列中的應用排序算法,可使用fair算法或者fifo算法 |
defaultMinSharePreemptionTimeout |
600 |
當獲得資源量小于最小共享量時,搶占資源之前可等待的時間 |
fairSharePreemptionTimeout |
600 |
當獲得資源量小于共享資源量時,搶占資源之前可等待的時間 |
7.一句話總結
如果,你剛接觸Hadoop的話,FifoScheduler會是個不錯的選擇。(話說2.0中的FifoScheduler的千年默認調度器位置被CapacityScheduler奪走,詳情查看YARN-137)
如果,你只是想控制下部分應用的優先級,同時又要最大化利用集群的話,選擇CapacityScheduler吧。
如果,你想很多人公平地共享資源的話,只有FairScheduler能滿足你。
資料參考:
http://dongxicheng.org/category/mapreduce-nextgen/ 博客中關于RM,NM,AM等多個部分的敘述,不一一說明
http://hadoop.apache.org/docs/r2.0.5-alpha/hadoop-YARN/hadoop-YARN-site/CapacityScheduler.html
http://hadoop.apache.org/docs/r2.0.5-alpha/hadoop-YARN/hadoop-YARN-site/FairScheduler.html Hadoop官方文檔中對著兩個調度器的說明
http://www.cloudera.com/content/cloudera/en/products/cdh.html CDH4的源碼
原文地址:YARN ResourceManager調度器的分析, 感謝原作者分享。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com