Yarn 調度器Scheduler

 

理想情況下,我們應用對Yarn資源的請求應該立刻得到滿足,但現實情況資源往往是有限的,特別是在一個很繁忙的集羣,一個應用資源的請求經常需要等待一段時間才能的到相應的資源。在Yarn中,負責給應用分配資源的就是Scheduler。其實調度本身就是一個難題,很難找到一個完美的策略可以解決所有的應用場景。爲此,Yarn提供了多種調度器和可配置的策略供我們選擇。

在Yarn中有三種調度器可以選擇:FIFO Scheduler ,Capacity Scheduler,Fair Scheduler

 

FIFO Scheduler

FIFO Scheduler把應用按提交的順序排成一個隊列,這是一個先進先出隊列,在進行資源分配的時候,先給隊列中最頭上的應用進行分配資源,待最頭上的應用需求滿足後再給下一個分配,以此類推。

 

FIFO Scheduler是最簡單也是最容易理解的調度器,也不需要任何配置,但它並不適用於共享集羣。大的應用可能會佔用所有集羣資源,這就導致其它應用被阻塞。在共享集羣中,更適合採用Capacity Scheduler或Fair Scheduler,這兩個調度器都允許大任務和小任務在提交的同時獲得一定的系統資源。

 

Capacity Scheduler

Capacity 調度器允許多個組織共享整個集羣,每個組織可以獲得集羣的一部分計算能力。通過爲每個組織分配專門的隊列,然後再爲每個隊列分配一定的集羣資源,這樣整個集羣就可以通過設置多個隊列的方式給多個組織提供服務了。除此之外,隊列內部又可以垂直劃分,這樣一個組織內部的多個成員就可以共享這個隊列資源了,在一個隊列內部,資源的調度是採用的是先進先出(FIFO)策略。

容量調度器 Capacity Scheduler 最初是由 Yahoo 最初開發設計使得 Hadoop 應用能夠被多用戶使用,且最大化整個集羣資源的吞吐量,現被 IBM BigInsights 和 Hortonworks HDP 所採用。

Capacity Scheduler 被設計爲允許應用程序在一個可預見的和簡單的方式共享集羣資源,即"作業隊列"。Capacity Scheduler 是根據租戶的需要和要求把現有的資源分配給運行的應用程序。Capacity Scheduler 同時允許應用程序訪問還沒有被使用的資源,以確保隊列之間共享其它隊列被允許的使用資源。管理員可以控制每個隊列的容量,Capacity Scheduler 負責把作業提交到隊列中。

 

​​​​​​​Fair Scheduler

在Fair調度器中,我們不需要預先佔用一定的系統資源,Fair調度器會爲所有運行的job動態的調整系統資源。如下圖所示,當第一個大job提交時,只有這一個job在運行,此時它獲得了所有集羣資源;當第二個小任務提交後,Fair調度器會分配一半資源給這個小任務,讓這兩個任務公平的共享集羣資源。

需要注意的是,在下圖Fair調度器中,從第二個任務提交到獲得資源會有一定的延遲,因爲它需要等待第一個任務釋放佔用的Container。小任務執行完成之後也會釋放自己佔用的資源,大任務又獲得了全部的系統資源。最終效果就是Fair調度器即得到了高的資源利用率又能保證小任務及時完成。

公平調度器 Fair Scheduler 最初是由 Facebook 開發設計使得 Hadoop 應用能夠被多用戶公平地共享整個集羣資源,現被 Cloudera CDH 所採用。

Fair Scheduler 不需要保留集羣的資源,因爲它會動態在所有正在運行的作業之間平衡資源。

 

示例:Capacity調度器配置使用

調度器的使用是通過yarn-site.xml配置文件中的

yarn.resourcemanager.scheduler.class參數進行配置的,默認採用Capacity Scheduler調度器

假設我們有如下層次的隊列:

root

├── prod

└── dev

    ├── mapreduce

    └── spark

下面是一個簡單的Capacity調度器的配置文件,文件名爲capacity-scheduler.xml。在這個配置中,在root隊列下面定義了兩個子隊列proddev,分別佔40%和60%的容量。需要注意,一個隊列的配置是通過屬性yarn.sheduler.capacity.<queue-path>.<sub-property>指定的,<queue-path>代表的是隊列的繼承樹,如root.prod隊列,<sub-property>一般指capacitymaximum-capacity

<configuration>
 <property>
    <name>yarn.scheduler.capacity.root.queues</name>
    <value>prod,dev</value>
  </property>
 <property>
    <name>yarn.scheduler.capacity.root.dev.queues</name>
    <value>mapreduce,spark</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.maximum-capacity</name>
    <value>75</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.dev.mapreduce.capacity</name>
    <value>50</value>
  </property>
   <property>
    <name>yarn.scheduler.capacity.root.dev.spark.capacity</name>
    <value>50</value>
  </property>
</configuration>

我們可以看到,dev隊列又被分成了mapreducespark兩個相同容量的子隊列。devmaximum-capacity屬性被設置成了75%,所以即使prod隊列完全空閒dev也不會佔用全部集羣資源,也就是說,prod隊列仍有25%的可用資源用來應急。我們注意到,mapreducespark兩個隊列沒有設置maximum-capacity屬性,也就是說mapreducespark隊列中的job可能會用到整個dev隊列的所有資源(最多爲集羣的75%)。而類似的,prod由於沒有設置maximum-capacity屬性,它有可能會佔用集羣全部資源。

關於隊列的設置,這取決於我們具體的應用。比如,在MapReduce中,我們可以通過mapreduce.job.queuename屬性指定要用的隊列。如果隊列不存在,我們在提交任務時就會收到錯誤。如果我們沒有定義任何隊列,所有的應用將會放在一個default隊列中。

注意:對於Capacity調度器,我們的隊列名必須是隊列樹中的最後一部分,如果我們使用隊列樹則不會被識別。比如,在上面配置中,我們使用prodmapreduce作爲隊列名是可以的,但是如果我們用root.dev.mapreduce或者dev. mapreduce是無效的。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章