本篇文章將深入介紹 Yarn 三種排程器。Yarn 本身作為資源管理和排程服務,其中的資源排程模組更是重中之重。下面將介紹 Yarn 中實現的排程器功能,以及內部執行邏輯。
Yarn 最主要的功能就是資源管理與分配。本篇文章將對資源分配中最核心的元件排程器(Scheduler)進行介紹。
排程器最理想的目標是有資源請求時,立即滿足。然而由於物理資源是有限的,就會存在資源如何分配的問題。針對不同資源需求量、不同優先順序、不同資源型別等,很難找到一個完美的策略可以解決所有的應用場景。因此,Yarn提供了多種排程器和可設定的策略供我們選擇。
Yarn 資源排程器均實現 ResourceScheduler 介面,是一個插拔式元件,使用者可以通過設定引數來使用不同的排程器,也可以自己按照介面規範編寫新的資源排程器。在 Yarn 中預設實現了三種調速器:FIFO Scheduler 、Capacity Scheduler、Fair Scheduler。
官方對三種排程器的介紹圖。看個大概意思就行,隨著排程器的不斷更新迭代,這個圖不再符合當下的情況。
最簡單的一個策略,僅做測試用。
用一個佇列來儲存提交等待的任務,先提交的任務就先分資源,有剩餘的資源就給後續排隊等待的任務,沒有資源了後續任務就等著之前的任務釋放資源。
優點:
簡單,開箱即用,不需要額外的設定。早些版本的 Yarn 用 FIFO 作為預設排程策略,後續改為 CapacityScheduler 作為預設排程策略。
缺點:
除了簡單外都是缺點,無法設定你各種想要的排程策略(限制資源量、限制使用者、資源搶奪等)。
Capacity Scheduler(後以 CS 簡寫代替)以佇列為單位劃分資源。會給每個佇列設定最小保證資源和最大可用資源。最小設定資源保證佇列一定能拿到這麼多資源,有空閒可共用給其他佇列使用;最大可用資源限制佇列最多能使用的資源,防止過度消耗。
佇列內部可以再巢狀,形成層級結構。佇列內資源預設採用 FIFO 的方式分配。如下圖所示。
優點:
缺點:
假設佇列層級如下:
root
├── prod
└── dev
├── eng
└── science
可以通過設定 capacity-scheduler.xml
來實現:
<configuration>
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>prod,dev</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.queues</name>
<value>eng,science</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.prod.capacity</name>
<value>40</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.capacity</name>
<value>60</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.eng.capacity</name>
<value>50</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.dev.science.capacity</name>
<value>50</value>
</property>
</configuration>
除了容量設定外,還可以設定單個使用者或者程式能夠使用的最大資源數,同時可以執行幾個應用,許可權ACL控制等,不是本篇重點,不再展開。可參考:cloudera - Capacity Scheduler、Hadoop doc - Capacity Scheduler、Hadoop: Capacity Scheduler yarn容量排程設定。
這裡僅關注 CS 資源分配的過程。
CS 分配的是各 NM 節點上的空閒資源,NM 資源彙報請到之前的文章《4-3 RM 管理 NodeManager》中瞭解。
AM 通過心跳彙報資源請求,包含的資訊如下。
message ResourceRequestProto {
optional PriorityProto priority = 1; // 優先順序
optional string resource_name = 2; // 期望資源所在節點或機架
optional ResourceProto capability = 3; // 資源量
optional int32 num_containers = 4; // Container 數目
optional bool relax_locality = 5 [default = true]; // 是否鬆弛本地性
optional string node_label_expression = 6; // 所在資源池
}
NM 傳送心跳給 RM 後,RM 會傳送 NODE_UPDATE
事件,這個事件會由 CapacityScheduler
進行處理。
case NODE_UPDATE:
{
NodeUpdateSchedulerEvent nodeUpdatedEvent = (NodeUpdateSchedulerEvent)event;
RMNode node = nodeUpdatedEvent.getRMNode();
setLastNodeUpdateTime(Time.now());
nodeUpdate(node);
if (!scheduleAsynchronously) {
// 重點
allocateContainersToNode(getNode(node.getNodeID()));
}
}
重點在 allocateContainersToNode()
,內部邏輯如下:
這裡有個預留的概念(之後會有文章專門介紹 reserve 機制):
同 Capacity Seheduler 類似,Fair Scheduler 也是一個多使用者排程器,它同樣新增了多層級別的資源限制條件以更好地讓多使用者共用一個 Hadoop 叢集,比如佇列資源限制、使用者應用程式數目限制等。
在 Fair 排程器中,我們不需要預先佔用一定的系統資源,Fair 排程器會為所有執行的 job 動態的調整系統資源。如下圖所示,當第一個大 job 提交時,只有這一個 job 在執行,此時它獲得了所有叢集資源;當第二個小任務提交後,Fair 排程器會分配一半資源給這個小任務,讓這兩個任務公平的共用叢集資源。
Fair 排程器的設計目標是為所有的應用分配公平的資源(對公平的定義可以通過引數來設定)。
優點:
在 FairScheduler 中是通過在 fair-scheduler.xml
中設定佇列權重,來實現「公平」的。
計算時是看(當前佇列權重 / 總權重)得到當前佇列能分得資源的百分比。
更詳細引數設定,可參考:Yarn 排程器Scheduler詳解
<queue name="first">
<minResources>512mb, 4vcores</minResources>
<maxResources>30720nb, 30vcores</maxResources>
<maxRunningApps>100</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>2.0</weight>
</queue>
<queue name="second">
<minResources>512mb, 4vcores</minResources>
<maxResources>30720nb, 30vcores</maxResources>
<maxRunningApps>100</maxRunningApps>
<schedulingMode>fair</schedulingMode>
<weight>1.0</weight>
</queue>
相同點
不同點
本篇介紹了 Yarn 中組重要的資源排程模組 ResourceScheduler,作為一個可插拔元件,預設有三種實現方式 Fifo、CapacityScheduler、FairScheduler。
文中對三個排程器的功能、特徵、設定、實現進行了較為詳細的分析。各位同學若對其中實現細節有興趣可深入原始碼,進一步探究。
參考文章:
YARN Capacity Scheduler (容量排程器) 不完全指南 | Bambrow's Blog - 對 CS 中設定屬性有較詳細講解
Capacity Scheduler - vs - Fair Scheduler
Yarn 排程器Scheduler詳解 - 對 Fair 佇列設定有較詳細講解
YARN排程器(Scheduler)詳解
詳解Yarn中三種資源排程器(FIFO Scheduler、Capacity Scheduler、Fair Scheduler)和設定自定義佇列實現任務提交不同佇列
Yarn Fair Scheduler詳解 - 原始碼分析
Yarn原始碼分析6-Reserve機制 | 亞坤的部落格 (yoelee.github.io)
YARN資源排程原理剖析
Hadoop 三大排程器原始碼分析及編寫自己的排程器