理想狀況下,咱們應用對Yarn資源的請求應該馬上獲得知足,但現實狀況資源每每是有限的,特別是在一個很繁忙的集羣,一個應用資源的請求常常須要等待一段時間才能的到相應的資源。在Yarn中,負責給應用分配資源的就是Scheduler。其實調度自己就是一個難題,很難找到一個完美的策略能夠解決全部的應用場景。爲此,Yarn提供了多種調度器和可配置的策略供咱們選擇。YARN架構以下:算法
FIFO Scheduler把應用按提交的順序排成一個隊列,這是一個先進先出隊列,在進行資源分配的時候,先給隊列中最頭上的應用進行分配資源,待最頭上的應用需求知足後再給下一個分配,以此類推。FIFO Scheduler是最簡單也是最容易理解的調度器,也不須要任何配置,但它並不適用於共享集羣。大的應用可能會佔用全部集羣資源,這就致使其它應用被阻塞。在共享集羣中,更適合採用Capacity Scheduler或Fair Scheduler,這兩個調度器都容許大任務和小任務在提交的同時得到必定的系統資源。下面「Yarn調度器對比圖」展現了這幾個調度器的區別,從圖中能夠看出,在FIFO 調度器中,小任務會被大任務阻塞。apache
yarn-site.xml中默認配置的資源調度器。而對於Capacity調度器,有一個專門的隊列用來運行小任務,可是爲小任務專門設置一個隊列會預先佔用必定的集羣資源,這就致使大任務的執行時間會落後於使用FIFO調度器時的時間。用這個資源調度器,就能夠配置yarn資源隊列,這個後面後介紹用到。網絡
Fair調度器的設計目標是爲全部的應用分配公平的資源(對公平的定義能夠經過參數來設置)。在上面的「Yarn調度器對比圖」展現了一個隊列中兩個應用的公平調度;固然,公平調度在也能夠在多個隊列間工做。舉個例子,假設有兩個用戶A和B,他們分別擁有一個隊列。當A啓動一個job而B沒有任務時,A會得到所有集羣資源;當B啓動一個job後,A的job會繼續運行,不過一下子以後兩個任務會各自得到一半的集羣資源。若是此時B再啓動第二個job而且其它job還在運行,則它將會和B的第一個job共享B這個隊列的資源,也就是B的兩個job會用於四分之一的集羣資源,而A的job仍然用於集羣一半的資源,結果就是資源最終在兩個用戶之間平等的共享。在Fair調度器中,咱們不須要預先佔用必定的系統資源,Fair調度器會爲全部運行的job動態的調整系統資源。當第一個大job提交時,只有這一個job在運行,此時它得到了全部集羣資源;當第二個小任務提交後,Fair調度器會分配一半資源給這個小任務,讓這兩個任務公平的共享集羣資源。
a) 公平調度器,就是可以共享整個集羣的資源
b) 不用預先佔用資源,每個做業都是共享的
c) 每當提交一個做業的時候,就會佔用整個資源。若是再提交一個做業,那麼第一個做業就會分給第二個做業一部分資源,第一個做業也就釋放一部分資源。再提交其餘的做業時,也同理。。。。也就是說每個做業進來,都有機會獲取資源。架構
yarn資源調度器是在yarn-site.xml中配置app
Fair Scheduler的配置選項包括兩部分:負載均衡
yarn-site.xml框架
<!– scheduler start –> <property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> <description>配置Yarn使用的調度器插件類名;Fair Scheduler對應的是:org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</description> </property> <property> <name>yarn.scheduler.fair.allocation.file</name> <value>/etc/hadoop/conf/fair-scheduler.xml</value> <description>配置資源池以及其屬性配額的XML文件路徑(本地路徑)</description> </property> <property> <name>yarn.scheduler.fair.preemption</name> <value>true</value> <description>開啓資源搶佔,default is True</description> </property> <property> <name>yarn.scheduler.fair.user-as-default-queue</name> <value>true</value> <description>設置成true,當任務中未指定資源池的時候,將以用戶名做爲資源池名。這個配置就實現了根據用戶名自動分配資源池。default is True</description> </property> <property> <name>yarn.scheduler.fair.allow-undeclared-pools</name> <value>false</value> <description>是否容許建立未定義的資源池。若是設置成true,yarn將會自動建立任務中指定的未定義過的資源池。設置成false以後,任務中指定的未定義的資源池將無效,該任務會被分配到default資源池中。,default is True</description> </property> <!– scheduler end –>
假設在生產環境Yarn中,總共有四類用戶須要使用集羣,production、spark、default、streaming。爲了使其提交的任務不受影響,咱們在Yarn上規劃配置了四個資源池,分別爲production,spark,default,streaming。並根據實際業務狀況,爲每一個資源池分配了相應的資源及優先級等,default用於開發測試目的.分佈式
ResourceManager上fair-scheduler.xml配置以下:oop
<?xml version="1.0"?> <allocations> <queue name="root"> <aclSubmitApps></aclSubmitApps> <aclAdministerApps></aclAdministerApps> <queue name="production"> <minResources>8192mb,8vcores</minResources> <maxResources>419840mb,125vcores</maxResources> <maxRunningApps>60</maxRunningApps> <schedulingMode>fair</schedulingMode> <weight>7.5</weight> <aclSubmitApps>*</aclSubmitApps> <aclAdministerApps>production</aclAdministerApps> </queue> <queue name="spark"> <minResources>8192mb,8vcores</minResources> <maxResources>376480mb,110vcores</maxResources> <maxRunningApps>50</maxRunningApps> <schedulingMode>fair</schedulingMode> <weight>1</weight> <aclSubmitApps>*</aclSubmitApps> <aclAdministerApps>spark</aclAdministerApps> </queue> <queue name="default"> <minResources>8192mb,8vcores</minResources> <maxResources>202400mb,20vcores</maxResources> <maxRunningApps>20</maxRunningApps> <schedulingMode>FIFO</schedulingMode> <weight>0.5</weight> <aclSubmitApps>*</aclSubmitApps> <aclAdministerApps>*</aclAdministerApps> </queue> <queue name="streaming"> <minResources>8192mb,8vcores</minResources> <maxResources>69120mb,16vcores</maxResources> <maxRunningApps>20</maxRunningApps> <schedulingMode>fair</schedulingMode> <aclSubmitApps>*</aclSubmitApps> <weight>1</weight> <aclAdministerApps>streaming</aclAdministerApps> </queue> </queue> <user name="production"> <!-- 對於特定用戶的配置:production最多能夠同時運行的任務 --> <maxRunningApps>100</maxRunningApps> </user> <user name="default"> <!-- 對於默認用戶配置最多能夠同時運行的任務 --> <maxRunningApps>10</maxRunningApps> </user> <!-- users max running apps --> <userMaxAppsDefault>50</userMaxAppsDefault> <!--默認的用戶最多能夠同時運行的任務 --> <queuePlacementPolicy> <rule name="specified"/> <rule name="primaryGroup" create="false" /> <rule name="secondaryGroupExistingQueue" create="false" /> <rule name="default" queue="default"/> </queuePlacementPolicy> </allocations>
參數介紹:測試
管理員也可爲單個用戶添加maxRunningJobs屬性限制其最多同時運行的應用程序數目。此外,管理員也可經過如下參數設置以上屬性的默認值:
這樣,每一個用戶組下的用戶提交任務時候,會到相應的資源池中,而不影響其餘業務。隊列的層次是經過嵌套<queue>元素實現的。全部的隊列都是root隊列的孩子,即便沒有配到<root>元素裏。Fair調度器中的隊列有一個權重屬性(這個權重就是對公平的定義),並把這個屬性做爲公平調度的依據。在這個例子中,當調度器分配集羣7.5,1,1,0.5資源給production,spark,streaming,default時便視做公平,這裏的權重並非百分比。注意,對於在沒有配置文件時按用戶自動建立的隊列,它們仍有權重而且權重值爲1。每一個隊列內部仍能夠有不一樣的調度策略。隊列的默認調度策略能夠經過頂級元素<defaultQueueSchedulingPolicy>進行配置,若是沒有配置,默認採用公平調度。儘管是Fair調度器,其仍支持在隊列級別進行FIFO調度。每一個隊列的調度策略能夠被其內部的<schedulingPolicy> 元素覆蓋,在上面這個例子中,default隊列就被指定採用fifo進行調度,因此,對於提交到default隊列的任務就能夠按照FIFO規則順序的執行了。須要注意,spark,production,streaming,default之間的調度仍然是公平調度。每一個隊列可配置最大、最小資源佔用數和最大可運行的應用的數量。
Fair調度器採用了一套基於規則的系統來肯定應用應該放到哪一個隊列。在上面的例子中,<queuePlacementPolicy> 元素定義了一個規則列表,其中的每一個規則會被逐個嘗試直到匹配成功。例如,上例第一個規則specified,則會把應用放到它指定的隊列中,若這個應用沒有指定隊列名或隊列名不存在,則說明不匹配這個規則,而後嘗試下一個規則。primaryGroup規則會嘗試把應用放在以用戶所在的Unix組名命名的隊列中,若是沒有這個隊列,不建立隊列轉而嘗試下一個規則。當前面全部規則不知足時,則觸發default規則,把應用放在default隊列中。
固然,咱們能夠不配置queuePlacementPolicy
規則,調度器則默認採用以下規則:
<queuePlacementPolicy> <rule name="specified" /> <rule name="user" /> </queuePlacementPolicy>
上面規則意思是除非隊列被準確的定義,不然會以用戶名爲隊列名建立隊列。還有一個簡單的配置策略可使得全部的應用放入同一個隊列(default),這樣就可讓全部應用之間平等共享集羣而不是在用戶之間。這個配置的定義以下:
<queuePlacementPolicy> <rule name="default" /> </queuePlacementPolicy>
實現上面功能咱們還能夠不使用配置文件,直接設置yarn.scheduler.fair.user-as-default-queue=false,這樣應用便會被放入default 隊列,而不是各個用戶名隊列。另外,咱們還能夠設置yarn.scheduler.fair.allow-undeclared-pools=false,這樣用戶就沒法建立隊列了。
當一個job提交到一個繁忙集羣中的空隊列時,job並不會立刻執行,而是阻塞直到正在運行的job釋放系統資源。爲了使提交job的執行時間更具預測性(能夠設置等待的超時時間),Fair調度器支持搶佔。搶佔就是容許調度器殺掉佔用超過其應占份額資源隊列的containers,這些containers資源即可被分配到應該享有這些份額資源的隊列中。須要注意搶佔會下降集羣的執行效率,由於被終止的containers須要被從新執行。能夠經過設置一個全局的參數yarn.scheduler.fair.preemption=true來啓用搶佔功能。此外,還有兩個參數用來控制搶佔的過時時間(這兩個參數默認沒有配置,須要至少配置一個來容許搶佔Container):
minSharePreemptionTimeout
fairSharePreemptionTimeout
若是隊列在minimum share preemption timeout指定的時間內未得到最小的資源保障,調度器就會搶佔containers。咱們能夠經過配置文件中的頂級元素<defaultMinSharePreemptionTimeout>爲全部隊列配置這個超時時間;咱們還能夠在<queue>元素內配置<minSharePreemptionTimeout>元素來爲某個隊列指定超時時間。
與之相似,若是隊列在fair share preemption timeout指定時間內未得到平等的資源的一半(這個比例能夠配置),調度器則會進行搶佔containers。這個超時時間能夠經過頂級元素<defaultFairSharePreemptionTimeout>和元素級元素<fairSharePreemptionTimeout>分別配置全部隊列和某個隊列的超時時間。上面提到的比例能夠經過<defaultFairSharePreemptionThreshold>(配置全部隊列)和<fairSharePreemptionThreshold>(配置某個隊列)進行配置,默認是0.5。
須要注意的是,全部客戶端提交任務的用戶和用戶組的對應關係,須要維護在ResourceManager上,ResourceManager在分配資源池時候,是從ResourceManager上讀取用戶和用戶組的對應關係的,不然就會被分配到default資源池。在日誌中出現」UserGroupInformation: No groups available for user」相似的警告。而客戶端機器上的用戶對應的用戶組可有可無。
每次在ResourceManager上新增用戶或者調整資源池配額後,須要執行下面的命令刷新使其生效.
yarn rmadmin -refreshQueues
yarn rmadmin -refreshUserToGroupsMappings
動態更新只支持修改資源池配額,若是是新增或減小資源池,則須要重啓Yarn集羣.
Fair Scheduer各資源池配置及使用狀況,在ResourceManager的WEB監控頁面上也能夠看到: http://ResourceManagerHost:8088/cluster/scheduler
Reference:
1.Hadoop多用戶資源管理–Fair Scheduler介紹與配置
hadoop2.7默認使用的是Capacity Scheduler容量調度器
yarn-site.xml
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.capacity.CapacityScheduler</value> </property>
Capacity 調度器容許多個組織共享整個集羣,每一個組織能夠得到集羣的一部分計算能力。經過爲每一個組織分配專門的隊列,而後再爲每一個隊列分配必定的集羣資源,這樣整個集羣就能夠經過設置多個隊列的方式給多個組織提供服務了。除此以外,隊列內部又能夠垂直劃分,這樣一個組織內部的多個成員就能夠共享這個隊列資源了,在一個隊列內部,資源的調度是採用的是先進先出(FIFO)策略。
一個job可能使用不了整個隊列的資源。然而若是這個隊列中運行多個job,若是這個隊列的資源夠用,那麼就分配給這些job,若是這個隊列的資源不夠用了呢?其實Capacity調度器仍可能分配額外的資源給這個隊列,這就是「彈性隊列」(queue elasticity)的概念。
在正常的操做中,Capacity調度器不會強制釋放Container,當一個隊列資源不夠用時,這個隊列只能得到其它隊列釋放後的Container資源。固然,咱們能夠爲隊列設置一個最大資源使用量,以避免這個隊列過多的佔用空閒資源,致使其它隊列沒法使用這些空閒資源,這就是」彈性隊列」須要權衡的地方。
假設咱們有以下層次的隊列:
root
├── prod
└── dev
├── eng
└── science
下面是一個簡單的Capacity調度器的配置文件,文件名爲capacity-scheduler.xml
。在這個配置中,在root隊列下面定義了兩個子隊列prod
和dev
,分別佔40%和60%的容量。須要注意,一個隊列的配置是經過屬性yarn.sheduler.capacity.<queue-path>.<sub-property>
指定的,<queue-path>
表明的是隊列的繼承樹,如root.prod
隊列,<sub-property>
通常指capacity
和maximum-capacity
。
咱們能夠看到,dev隊列又被分紅了eng和science兩個相同容量的子隊列。dev的maximum-capacity屬性被設置成了75%,因此即便prod隊列徹底空閒dev也不會佔用所有集羣資源,也就是說,prod隊列仍有25%的可用資源用來應急。咱們注意到,eng和science兩個隊列沒有設置maximum-capacity屬性,也就是說eng或science隊列中的job可能會用到整個dev隊列的全部資源(最多爲集羣的75%)。而相似的,prod因爲沒有設置maximum-capacity屬性,它有可能會佔用集羣所有資源。Capacity容器除了能夠配置隊列及其容量外,咱們還能夠配置一個用戶或應用能夠分配的最大資源數量、能夠同時運行多少應用、隊列的ACL認證等。
關於隊列的設置,這取決於咱們具體的應用。好比,在MapReduce中,咱們能夠經過mapreduce.job.queuename屬性指定要用的隊列。若是隊列不存在,咱們在提交任務時就會收到錯誤。若是咱們沒有定義任何隊列,全部的應用將會放在一個default隊列中。
注意:對於Capacity調度器,咱們的隊列名必須是隊列樹中的最後一部分,若是咱們使用隊列樹則不會被識別。好比,在上面配置中,咱們使用prod和eng做爲隊列名是能夠的,可是若是咱們用root.dev.eng或者dev.eng是無效的。
yarn-site.xml
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.fifo.FifoScheduler</value> </property>