- 隨著Hadoop的普及,單個Hadoop集群的用戶量越來越大,不同用戶提交的應用程序往往具有不同的服務質量要求,典型的應用有以下幾種:
- 批處理作業。這種作業往往耗時較長,對完成時間一般沒有嚴格要求,如數據挖掘、機器學習等方面的應用程序
- 交互式作業。這種作業期望能及時返回結果,如用HIVE執行查詢
- 生產性作業。這種作業要求有一定量的資源保證,如統計值計算、垃圾數據分析等
基本架構
- 資源調度器是YARN中最核心的組件之一,且是插拔式的,它定義了一整套接口規范以便用戶可按照需要實現自己的調度器
- YARN自帶FIFO、Capacity Scheduler和Fair Scheduler三種常用資源調度器,當然,用戶可按照接口規范編寫一個新的資源調度器,并通過簡單的配置使它運行起來
- YARN的資源管理器實際上是一個事件處理器,它需要處理來自外部的6種Scheduler-EventType類型的事件,并根據事件的具體含義進行相應的處理,6種事件含義如下:
- NODE_REMOVED:表示集群中移除了一個計算節點(可能是節點故障或者管理員主動移除),資源調度器收到該事件時需要從可分配資源總量中移除相應的資源
- NODE_ADDED:表示集群中增加了一個計算節點,資源調度器收到該事件時需要將新增的資源量添加到可分配資源總量中
- APPLICATION_ADDED:表示ResourceManager收到一個新的Application。通常而言,資源管理器需要為每個Application維護一個獨立的數據結構,以便于統一管理和資源分配。資源管理器將該Application添加到相應的數據結構中
- APPLICATION_REMOVED:表示一個Application運行結束(可能成功或失敗),資源管理器將該Application從相應的數據結構中清除
- CONTAINER_EXPIRED:當資源調度器將一個Container分配給某個Application-Master后,如果該ApplicationMaster在一定時間內沒有使用該Container,則資源調度器會對該Container進行(回收后)再分配
- NODE_UPDATE:ResourceManager收到NodeManager通過心跳機制匯報的信息后,會觸發一個NODE_UPDATE事件,由于此時可能有新的Container得到釋放,因此該事件會觸發資源分配。也就是說,該事件是6個事件中最重要的事件,它會觸發資源調度器最核心的資源分配機制
資源表示模型
- NodeManager啟動時會向ResourceManager注冊,注冊信息中包含該節點可分配的CPU和內存總量,這兩個值均可通過配置選項設置,具體如下:
-
yarn.nodemanager.resource.memory-mb
:可分配的物理內存總量,默認是8G -
yarn.nodemanager.vmem-pmem-ratio
:任務使用單位物理內存量對應最多可使用的虛擬內存,默認值是2.1,表示使用1M的物理內存,最多可以使用2.1MB的虛擬內存總量 -
yarn.nodemanager.resource.cpu-vcores
:可分配的虛擬CPU個數,默認是8。為了更細粒度地劃分CPU資源和考慮到CPU性能差異,YARN允許管理員根據實際需要和CPU性能將每個物理CPU劃分成若干個虛擬CPU,而管理員可為每個節點單獨配置可用的虛擬CPU個數,且用戶提交應用程序時,也可指定每個任務需要的虛擬CPU數
-
- YARN支持的調度語義:
- 請求某個節點上的特定資源量
- 請求某個特定機架上的特定資源量
- 將某些節點加入(或移除)黑名單,不再為自己分配這些節點上的資源
- 請求歸還某些資源
- 不支持的調度語義:
- 請求任意節點上的特定資源量
- 請求任意機架上的特定資源量
- 請求一組或幾組符合某種特質的資源
- 超細粒度資源。比如CPU性能要求、綁定CPU等
- 動態調整Container資源,允許根據需要動態調整Container資源量
資源調度模型
- YARN采用了雙層資源調度模型
- 第一層中,ResourceManager中的資源調度器將資源分配給各個ApplicationMaster
- 第二層中,ApplicationMaster再進一步將資源分配給它的內部任務
- YARN的資源分配過程是異步的,也就是說,資源調度器將資源分配給一個應用程序后,它不會立刻push給對應的ApplicationMaster,而是暫時放到一個緩沖區中,等待ApplicationMaster通過周期性的心跳主動來取(pull-based通信模型)
- YARN采用了增量資源分配機制(當應用程序申請的資源暫時無法保證時,為應用程序預留一個節點上的資源直到累計釋放的空閑資源滿足應用程序需求),這種機制會造成浪費,但不會出現餓死現象
- YARN資源調度器采用了主資源公平調度算法,DRF的基本設計思想則是將最大最小化公平算法應用于主資源上,進而將多維資源調度問題轉化為單資源調度問題,即DRF總是最大化所有主資源中最小的
資源搶占模型
- 在資源調度器中,每個隊列可設置一個最小資源量和最大資源量,其中,最小資源量是資源緊缺情況下每個隊列需保證的資源量,而最大資源量則是極端情況下隊列也不能超過的資源使用量
- 為了提高資源利用率,資源調度器(包括Capacity Scheduler和Fair Scheduler)會將負載較輕的隊列的資源暫時分配給負載重的隊列(即最小資源量并不是硬資源保證,當隊列不需要任何資源時,并不會滿足它的最小資源量,而是暫時將空閑資源分配給其他需要資源的隊列),僅當負載較輕隊列突然收到新提交的應用程序時,調度器才進一步將本屬于該隊列的資源分配給它。但由于此時資源可能正被其他隊列使用,因此調度器必須等待其他隊列釋放資源后,才能將這些資源“物歸原主”,這通常需要一段不確定的等待時間。為了防止應用程序等待時間過長,調度器等待一段時間后若發現資源并未得到釋放,則進行資源搶占
- 僅當啟用的調度器實現了PreemptableResourceScheduler接口,且參數
yarn.resourcemanager.secheduler.monitor.enable
的值被置為true(默認值為false)時,ResourceManager才啟用資源搶占功能。資源搶占是通過第三方策略觸發的,這些策略被實現成一些插拔式的組件類(實現SchedulingEditPolicy接口),并通過參數yarn.resourcemanager.schduler.monitor.policies
指定(默認情況下,YARN提供了默認實現ProporitonalCapacityPreemptionPolicy) - ResourceManager將依次遍歷這些策略類,并由監控類SchedulingMonitor進一步封裝它們,SchedulingMonitor將周期性調用策略類的editSchedule()函數,以決定搶占哪些Container的資源
- 在YARN中,資源搶占整個過程可概括為如下步驟:
- SchedulingEditPolicy探測到需要搶占的資源,將需要搶占的資源通過事件DROP_RESERVATION和PREEMPT_CONTAINER發送給ResourceManager
- ResourceManager調用ResourceScheduler的dropContainerReservation和preemptContainer函數,標注待搶占的Container
- ResourceManager收到來自ApplicationMaster的心跳信息,并通過心跳應答將待釋放的資源總量和待搶占Container列表返回給它。ApplicationMaster收到該列表后,可選擇如下操作:
- 殺死這些Container
- 選擇并殺死其他Container以湊夠總量
- 不做任何處理,過段時間可能有Container自行釋放資源或者由ResourceManager殺死Container
- SchedulingEditPolicy探測到一段時間內,ApplicationMaster未自行殺死約定的Container,則將這些Container封裝到KILL_CONTAINER事件中發送給ResourceManager
- ResourceManager調用ResourceScheduler的killContainer函數,而ResourceScheduler則標注這些待殺死的Container
- ResourceManager收到來自NodeManager的心跳信息,并通過心跳應答將待殺死的Container列表返回給它,NodeManager收到該列表后,將這些Container殺死,并通過心跳告知ResourceManager
- ResourceManager收到來自ApplicationMaster的心跳信息,并通過心跳應答將已殺死的Container列表發送給它
- 在YARN中,隊列是按照樹形結構組織的,一個隊列當前實際可以使用的資源量R取決于最小資源量A(由管理員配置)、隊列資源需求量(處于等待或者運行狀態的應用程序尚需的資源總量)和同父兄弟隊列的空閑資源量C(多余資源可共享給其他隊列),這意味著R在不同時間點的取值是不同的,可以按照遞歸算法求出R=F(A, B, C),這樣,如果一個隊列當前正在使用資源量U>R,則需從該隊列中搶占(U-R)資源
- 為了盡可能避免資源浪費,YARN優先選擇優先級低的Container作為資源搶占對象,且不會立刻殺死Container,而是將釋放資源的任務留給應用程序自己:ResourceManager將待殺死的Container列表發送給對應的ApplicationMaster,以期望它采取一定的機制自行釋放這些Container占用的資源,比如先進行一些狀態保存工作后,再將對應的Container殺死,以避免計算浪費,如果一段時間后,ApplicationMaster尚未主動殺死這些Container,則ResourceManager再強制殺死這些Container
層級隊列管理機制
- 層級隊列組織方式具有以下特點:
- 子隊列
- 隊列可以嵌套,每個隊列可以包含子隊列
- 用戶只能將應用程序提交到最底層的隊列,即葉子隊列
- 最少容量
- 每個子隊列均有一個“最少容量比”屬性,表示可以使用父隊列的容量百分比
- 調度器總是優先選擇當前資源使用率(當時使用的/最少容量)最低的隊列,并為之分配資源
- 最少容量不是“總會保證的最低容量”,也就是說,如果一個隊列的最少容量為20,而該隊列中所有隊列僅使用了5,那么剩下的15可能會分配給其他需要的隊列
- 最少容量的值為不小于0的數,但也不能大于“最大容量”
- 最大容量
- 為了防止一個隊列超量使用資源,可以為隊列設置一個最大容量,這是一個資源使用上限,任何時刻使用的資源總量都不能超過該值
- 默認情況下隊列的最大容量是無限大,這意味著,當一個隊列只分配了20%的資源,所有其他隊列沒有應用程序時,該隊列可能使用100%的資源,當其他隊列有應用程序提交時,再逐步歸還
- 用戶權限管理
- 管理員可配置每個葉子隊列對應的操作系統用戶和用戶組(Hadoop允許一個操作系統用戶或者用戶組可對應一個或多個隊列),也可以配置每個隊列的管理員,他可以殺死該隊列中任何應用程序,改變任何應用程序的優先級等(默認情況下用戶只能管理自己的應用程序)
- 系統資源管理
- YARN資源管理和調度均由調度器完成,管理員可在調度器中設置每個隊列的資源容量,每個用戶資源量等信息,而調度器則按照這些資源約束對應用程序進行調度
- 子隊列
參考:《Hadoop 技術內幕:深入解析 YARN 架構設計與實現原理》