Hadoop YARN同時支持內存和CPU兩種資源的調度,本文介紹如何配置YARN對內存和CPU的使用。
YARN作爲一個資源調度器,應該考慮到集羣裏面每一臺機子的計算資源,然後根據application申請的資源進行分配Container。Container是YARN裏面資源分配的基本單位,具有一定的內存以及CPU資源。
在YARN集羣中,平衡內存、CPU、磁盤的資源的很重要的,根據經驗,每兩個container使用一塊磁盤以及一個CPU核的時候可以使集羣的資源得到一個比較好的利用。
內存配置
關於內存相關的配置可以參考hortonwork公司的文檔Determine HDP Memory Configuration Settings來配置你的集羣。
YARN以及MAPREDUCE所有可用的內存資源應該要除去系統運行需要的以及其他的hadoop的一些程序,總共保留的內存=系統內存+HBASE內存。
可以參考下面的表格確定應該保留的內存:
每臺機子內存 | 系統需要的內存 | HBase需要的內存 |
---|---|---|
4GB | 1GB | 1GB |
8GB | 2GB | 1GB |
16GB | 2GB | 2GB |
24GB | 4GB | 4GB |
48GB | 6GB | 8GB |
64GB | 8GB | 8GB |
72GB | 8GB | 8GB |
96GB | 12GB | 16GB |
128GB | 24GB | 24GB |
255GB | 32GB | 32GB |
512GB | 64GB | 64GB |
計算每臺機子最多可以擁有多少個container,可以使用下面的公式:
containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)
說明:
- CORES爲機器CPU核數
- DISKS爲機器上掛載的磁盤個數
- Total available RAM爲機器總內存
- MIN_CONTAINER_SIZE是指container最小的容量大小,這需要根據具體情況去設置,可以參考下面的表格:
每臺機子可用的RAM | container最小值 |
---|---|
小於4GB | 256MB |
4GB到8GB之間 | 512MB |
8GB到24GB之間 | 1024MB |
大於24GB | 2048MB |
每個container的平均使用內存大小計算方式爲:
RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
通過上面的計算,YARN以及MAPREDUCE可以這樣配置:
配置文件 | 配置設置 | 默認值 | 計算值 |
---|---|---|---|
yarn-site.xml | yarn.nodemanager.resource.memory-mb | 8192 MB | = containers * RAM-per-container |
yarn-site.xml | yarn.scheduler.minimum-allocation-mb | 1024MB | = RAM-per-container |
yarn-site.xml | yarn.scheduler.maximum-allocation-mb | 8192 MB | = containers * RAM-per-container |
yarn-site.xml (check) | yarn.app.mapreduce.am.resource.mb | 1536 MB | = 2 * RAM-per-container |
yarn-site.xml (check) | yarn.app.mapreduce.am.command-opts | -Xmx1024m | = 0.8 * 2 * RAM-per-container |
mapred-site.xml | mapreduce.map.memory.mb | 1024 MB | = RAM-per-container |
mapred-site.xml | mapreduce.reduce.memory.mb | 1024 MB | = 2 * RAM-per-container |
mapred-site.xml | mapreduce.map.java.opts | = 0.8 * RAM-per-container | |
mapred-site.xml | mapreduce.reduce.java.opts | = 0.8 * 2 * RAM-per-container |
舉個例子:對於128G內存、32核CPU的機器,掛載了7個磁盤,根據上面的說明,系統保留內存爲24G,不適應HBase情況下,系統剩餘可用內存爲104G,計算containers值如下:
containers = min (2*32, 1.8* 7 , (128-24)/2) = min (64, 12.6 , 51) = 13
計算RAM-per-container值如下:
RAM-per-container = max (2, (124-24)/13) = max (2, 8) = 8
你也可以使用腳本yarn-utils.py來計算上面的值:
點擊(此處)摺疊或打開
- #!/usr/bin/env python
- import optparse
- from pprint import pprint
- import logging
- import sys
- import math
- import ast
- ''' Reserved for OS + DN + NM, Map: Memory => Reservation '''
- reservedStack = { 4:1, 8:2, 16:2, 24:4, 48:6, 64:8, 72:8, 96:12,
- 128:24, 256:32, 512:64}
- ''' Reserved for HBase. Map: Memory => Reservation '''
- reservedHBase = {4:1, 8:1, 16:2, 24:4, 48:8, 64:8, 72:8, 96:16,
- 128:24, 256:32, 512:64}
- GB = 1024
- def getMinContainerSize(memory):
- if (memory <= 4):
- return 256
- elif (memory <= 8):
- return 512
- elif (memory <= 24):
- return 1024
- else:
- return 2048
- pass
- def getReservedStackMemory(memory):
- if (reservedStack.has_key(memory)):
- return reservedStack[memory]
- if (memory <= 4):
- ret = 1
- elif (memory >= 512):
- ret = 64
- else:
- ret = 1
- return ret
- def getReservedHBaseMem(memory):
- if (reservedHBase.has_key(memory)):
- return reservedHBase[memory]
- if (memory <= 4):
- ret = 1
- elif (memory >= 512):
- ret = 64
- else:
- ret = 2
- return ret
- def main():
- log = logging.getLogger(__name__)
- out_hdlr = logging.StreamHandler(sys.stdout)
- out_hdlr.setFormatter(logging.Formatter(' %(message)s'))
- out_hdlr.setLevel(logging.INFO)
- log.addHandler(out_hdlr)
- log.setLevel(logging.INFO)
- parser = optparse.OptionParser()
- memory = 0
- cores = 0
- disks = 0
- hbaseEnabled = True
- parser.add_option('-c', '--cores', default = 16,
- help = 'Number of cores on each host')
- parser.add_option('-m', '--memory', default = 64,
- help = 'Amount of Memory on each host in GB')
- parser.add_option('-d', '--disks', default = 4,
- help = 'Number of disks on each host')
- parser.add_option('-k', '--hbase', default = "True",
- help = 'True if HBase is installed, False is not')
- (options, args) = parser.parse_args()
- cores = int (options.cores)
- memory = int (options.memory)
- disks = int (options.disks)
- hbaseEnabled = ast.literal_eval(options.hbase)
- log.info("Using cores=" + str(cores) + " memory=" + str(memory) + "GB" +
- " disks=" + str(disks) + " hbase=" + str(hbaseEnabled))
- minContainerSize = getMinContainerSize(memory)
- reservedStackMemory = getReservedStackMemory(memory)
- reservedHBaseMemory = 0
- if (hbaseEnabled):
- reservedHBaseMemory = getReservedHBaseMem(memory)
- reservedMem = reservedStackMemory + reservedHBaseMemory
- usableMem = memory - reservedMem
- memory -= (reservedMem)
- if (memory < 2):
- memory = 2
- reservedMem = max(0, memory - reservedMem)
- memory *= GB
- containers = int (min(2 * cores,
- min(math.ceil(1.8 * float(disks)),
- memory/minContainerSize)))
- if (containers <= 2):
- containers = 3
- log.info("Profile: cores=" + str(cores) + " memory=" + str(memory) + "MB"
- + " reserved=" + str(reservedMem) + "GB" + " usableMem="
- + str(usableMem) + "GB" + " disks=" + str(disks))
- container_ram = abs(memory/containers)
- if (container_ram > GB):
- container_ram = int(math.floor(container_ram / 512)) * 512
- log.info("Num Container=" + str(containers))
- log.info("Container Ram=" + str(container_ram) + "MB")
- log.info("Used Ram=" + str(int (containers*container_ram/float(GB))) + "GB")
- log.info("Unused Ram=" + str(reservedMem) + "GB")
- log.info("yarn.scheduler.minimum-allocation-mb=" + str(container_ram))
- log.info("yarn.scheduler.maximum-allocation-mb=" + str(containers*container_ram))
- log.info("yarn.nodemanager.resource.memory-mb=" + str(containers*container_ram))
- map_memory = container_ram
- reduce_memory = 2*container_ram if (container_ram <= 2048) else container_ram
- am_memory = max(map_memory, reduce_memory)
- log.info("mapreduce.map.memory.mb=" + str(map_memory))
- log.info("mapreduce.map.java.opts=-Xmx" + str(int(0.8 * map_memory)) +"m")
- log.info("mapreduce.reduce.memory.mb=" + str(reduce_memory))
- log.info("mapreduce.reduce.java.opts=-Xmx" + str(int(0.8 * reduce_memory)) + "m")
- log.info("yarn.app.mapreduce.am.resource.mb=" + str(am_memory))
- log.info("yarn.app.mapreduce.am.command-opts=-Xmx" + str(int(0.8*am_memory)) + "m")
- log.info("mapreduce.task.io.sort.mb=" + str(int(0.4 * map_memory)))
- pass
- if __name__ == '__main__':
- try:
- main()
- except(KeyboardInterrupt, EOFError):
- print("\nAborting ... Keyboard Interrupt.")
- sys.exit(1)
執行下面命令:
python yarn-utils.py -c 32 -m 128 -d 7 -k False
返回結果如下:
點擊(此處)摺疊或打開
- Using cores=32 memory=128GB disks=7 hbase=False
- Profile: cores=32 memory=106496MB reserved=24GB usableMem=104GB disks=7
- Num Container=13
- Container Ram=8192MB
- Used Ram=104GB
- Unused Ram=24GB
- yarn.scheduler.minimum-allocation-mb=8192
- yarn.scheduler.maximum-allocation-mb=106496
- yarn.nodemanager.resource.memory-mb=106496
- mapreduce.map.memory.mb=8192
- mapreduce.map.java.opts=-Xmx6553m
- mapreduce.reduce.memory.mb=8192
- mapreduce.reduce.java.opts=-Xmx6553m
- yarn.app.mapreduce.am.resource.mb=8192
- yarn.app.mapreduce.am.command-opts=-Xmx6553m
- mapreduce.task.io.sort.mb=3276
這樣的話,每個container內存爲8G,似乎有點多,我更願意根據集羣使用情況任務將其調整爲2G內存,則集羣中下面的參數配置值如下:
配置文件 | 配置設置 | 計算值 |
---|---|---|
yarn-site.xml | yarn.nodemanager.resource.memory-mb | = 52 * 2 =104 G |
yarn-site.xml | yarn.scheduler.minimum-allocation-mb | = 2G |
yarn-site.xml | yarn.scheduler.maximum-allocation-mb | = 52 * 2 = 104G |
yarn-site.xml (check) | yarn.app.mapreduce.am.resource.mb | = 2 * 2=4G |
yarn-site.xml (check) | yarn.app.mapreduce.am.command-opts | = 0.8 * 2 * 2=3.2G |
mapred-site.xml | mapreduce.map.memory.mb | = 2G |
mapred-site.xml | mapreduce.reduce.memory.mb | = 2 * 2=4G |
mapred-site.xml | mapreduce.map.java.opts | = 0.8 * 2=1.6G |
mapred-site.xml | mapreduce.reduce.java.opts | = 0.8 * 2 * 2=3.2G |
對應的xml配置爲:
點擊(此處)摺疊或打開
- <property>
- <name>yarn.nodemanager.resource.memory-mb</name>
- <value>106496</value>
- </property>
- <property>
- <name>yarn.scheduler.minimum-allocation-mb</name>
- <value>2048</value>
- </property>
- <property>
- <name>yarn.scheduler.maximum-allocation-mb</name>
- <value>106496</value>
- </property>
- <property>
- <name>yarn.app.mapreduce.am.resource.mb</name>
- <value>4096</value>
- </property>
- <property>
- <name>yarn.app.mapreduce.am.command-opts</name>
- <value>-Xmx3276m</value>
- </property>
另外,還有一下幾個參數:
- yarn.nodemanager.vmem-pmem-ratio:任務每使用1MB物理內存,最多可使用虛擬內存量,默認是2.1。
- yarn.nodemanager.pmem-check-enabled:是否啓動一個線程檢查每個任務正使用的物理內存量,如果任務超出分配值,則直接將其殺掉,默認是true。
- yarn.nodemanager.vmem-pmem-ratio:是否啓動一個線程檢查每個任務正使用的虛擬內存量,如果任務超出分配值,則直接將其殺掉,默認是true。
第一個參數的意思是當一個map任務總共分配的物理內存爲2G的時候,該任務的container最多內分配的堆內存爲1.6G,可以分配的虛擬內存上限爲2*2.1=4.2G。另外,照這樣算下去,每個節點上YARN可以啓動的Map數爲104/2=52個。
CPU配置
YARN中目前的CPU被劃分成虛擬CPU(CPU virtual Core),這裏的虛擬CPU是YARN自己引入的概念,初衷是,考慮到不同節點的CPU性能可能不同,每個CPU具有的計算能力也是不一樣的,比如某個物理CPU的計算能力可能是另外一個物理CPU的2倍,這時候,你可以通過爲第一個物理CPU多配置幾個虛擬CPU彌補這種差異。用戶提交作業時,可以指定每個任務需要的虛擬CPU個數。
在YARN中,CPU相關配置參數如下:
- yarn.nodemanager.resource.cpu-vcores:表示該節點上YARN可使用的虛擬CPU個數,默認是8,注意,目前推薦將該值設值爲與物理CPU核數數目相同。如果你的節點CPU核數不夠8個,則需要調減小這個值,而YARN不會智能的探測節點的物理CPU總數。
- yarn.scheduler.minimum-allocation-vcores:單個任務可申請的最小虛擬CPU個數,默認是1,如果一個任務申請的CPU個數少於該數,則該對應的值改爲這個數。
- yarn.scheduler.maximum-allocation-vcores:單個任務可申請的最多虛擬CPU個數,默認是32。
對於一個CPU核數較多的集羣來說,上面的默認配置顯然是不合適的,在我的測試集羣中,4個節點每個機器CPU核數爲31,留一個給操作系統,可以配置爲:
點擊(此處)摺疊或打開
- <property>
- <name>yarn.nodemanager.resource.cpu-vcores</name>
- <value>31</value>
- </property>
- <property>
- <name>yarn.scheduler.maximum-allocation-vcores</name>
- <value>124</value>
- </property>
把CDH搭建起來了,跑其中的例子程序word-count。在控制檯界面一直顯示map 0% reduce 0% , 通過web頁面查看job的狀態一直是run,但是map沒有執行。感覺是是資源的分配有問題。接着查看了任務的日誌。
2014-07-04 17:30:37,492 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Recalculating schedule, headroom=0 2014-07-04 17:30:37,492 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Reduce slow start threshold not met. completedMapsForReduceSlowstart 2 2014-07-04 17:30:38,496 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Ramping down all scheduled reduces:0 2014-07-04 17:30:38,496 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Going to preempt 0
日誌中沒有任何的錯誤,但是一直打印該信息,應該是RM資源分配不夠。
YARN中,資源包括內存和CPU,資源的管理是由ResourceManager和NodeManager共同完成,ResourceManager負責所有節點資源的管理和調度。NodeManager負責進程所在結點資源的分配和隔離。ResourceManager將某個NodeManager上資源分配給任務。下面詳細介紹其中的一些重要參數。
yarn.nodemanager.resource.memory-mb
每個節點可用的內存, 它的單 位是mb,默認是8G,用於供NodeManager分配的。我出現的問題是資源分配太小,只有1G。
yarn.scheduler.minimum-allocation-mb
單個任務可申請的最小內存,默認是1024mb,稍微大一點,避免小的資源浪費情況,我本機資源少,所以給他分配了512mb, 失敗的原因也就是這個分配過大。
yarn.scheduler.maximum-allocation-mb
單個任務可申請的最大內存,默認是8192mb. 如果是spark任務的話,這裏調大吧
mapreduce.map.memory.mb
每個map任務的物理內存限制,應該大於或等於yarn.scheduler.minimum-allocation-mb
mapreduce.reduce.memory.mb
每個reduce任務的物理內存限制
mapreduce.map.java.opts
每個map進程的jvm堆的大小
mapreduce.reduce.java.opts
每個reduce進程的jvm堆的大小
每個節點可以運行map數和redue輸,由yarn.nodemanager.resource.memory-mb除於mapreduce.map.memory.mb和mapreduce.reduce.memory.mb得到
yarn資源memory與core計算配置
yarn調度分配主要是針對Memory與CPU進行管理分配,並將其組合抽象成container來管理計算使用
memory配置
計算每臺機子最多可以擁有多少個container:
containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)
說明:
CORES爲機器CPU核數
DISKS爲機器上掛載的磁盤個數
Total available RAM爲機器總內存
MIN_CONTAINER_SIZE是指container最小的容量大小,這需要根據具體情況去設置,可以參考下面的表格:
每個container的平均使用內存大小計算方式爲:
RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
相關配置調整說明:
(1)yarn.nodemanager.resource.memory-mb 表示該節點上YARN可使用的物理內存總量,默認是8192(MB),注意,如果你的節點內存資源不夠8GB,則需要調減小這個值,而YARN不會智能的探測節點的物理內存總量。 (2)yarn.nodemanager.vmem-pmem-ratio 任務每使用1MB物理內存,最多可使用虛擬內存量,默認是2.1。 (3) yarn.nodemanager.pmem-check-enabled 是否啓動一個線程檢查每個任務正使用的物理內存量,如果任務超出分配值,則直接將其殺掉,默認是true。 (4) yarn.nodemanager.vmem-check-enabled 是否啓動一個線程檢查每個任務正使用的虛擬內存量,如果任務超出分配值,則直接將其殺掉,默認是true。 (5)yarn.scheduler.minimum-allocation-mb 單個container可申請的最少物理內存量,默認是1024(MB),如果一個任務申請的物理內存量少於該值,則該對應的值改爲這個數。 (6)yarn.scheduler.maximum-allocation-mb 單個container可申請的最多物理內存量,默認是8192(MB)。
默認情況下,YARN採用了線程監控的方法判斷任務是否超量使用內存,一旦發現超量,則直接將其殺死。由於Cgroups對內存的控制缺乏靈活性(即任務任何時刻不能超過內存上限,如果超過,則直接將其殺死或者報OOM),而Java進程在創建瞬間內存將翻倍,之後驟降到正常值,這種情況下,採用線程監控的方式更加靈活(當發現進程樹內存瞬間翻倍超過設定值時,可認爲是正常現象,不會將任務殺死),因此YARN未提供Cgroups內存隔離機制。
CPU配置
在yarn中使用的是虛擬CPU,這裏的虛擬CPU是YARN自己引入的概念,初衷是,考慮到不同節點的CPU性能可能不同,每個CPU具有的計算能力也是不一樣的,比如某個物理CPU的計算能力可能是另外一個物理CPU的2倍,這時候,你可以通過爲第一個物理CPU多配置幾個虛擬CPU彌補這種差異。用戶提交作業時,可以指定每個任務需要的虛擬CPU個數。在YARN中,CPU相關配置參數如下:
(1)yarn.nodemanager.resource.cpu-vcores 表示該節點上YARN可使用的虛擬CPU個數,默認是8,注意,目前推薦將該值設值爲與物理CPU核數數目相同。 如果你的節點CPU核數不夠8個,則需要調減小這個值,而YARN不會智能的探測節點的物理CPU總數。 (2)yarn.scheduler.minimum-allocation-vcores 單個任務可申請的最小虛擬CPU個數,默認是1,如果一個任務申請的CPU個數少於該數,則該對應的值改爲這個數。 (3)yarn.scheduler.maximum-allocation-vcores 單個任務可申請的最多虛擬CPU個數,默認是32。
默認情況下,YARN是不會對CPU資源進行調度的,你需要配置相應的資源調度器讓你支持,具體參看以下鏈接:
(1)Hadoop YARN配置參數剖析(4)—Fair Scheduler相關參數
(2)Hadoop YARN配置參數剖析(5)—Capacity Scheduler相關參數
默認情況下,NodeManager不會對CPU資源進行任何隔離,你可以通過啓用Cgroups讓你支持CPU隔離。
由於CPU資源的獨特性,目前這種CPU分配方式仍然是粗粒度的。舉個例子,很多任務可能是IO密集型的,消耗的CPU資源非常少,如果此時你爲它分配一個CPU,則是一種嚴重浪費,你完全可以讓他與其他幾個任務公用一個CPU,也就是說,我們需要支持更粒度的CPU表達方式。
借鑑亞馬遜EC2中CPU資源的劃分方式,即提出了CPU最小單位爲EC2 Compute Unit(ECU),一個ECU代表相當於1.0-1.2 GHz 2007 Opteron or 2007 Xeon處理器的處理能力。YARN提出了CPU最小單位YARN Compute Unit(YCU),目前這個數是一個整數,默認是720,由參數yarn.nodemanager.resource.cpu-ycus-per-core設置,表示一個CPU core具備的計算能力(該feature在2.2.0版本中並不存在,可能增加到2.3.0版本中),這樣,用戶提交作業時,直接指定需要的YCU即可,比如指定值爲360,表示用1/2個CPU core,實際表現爲,只使用一個CPU core的1/2計算時間。注意,在操作系統層,CPU資源是按照時間片分配的,你可以說,一個進程使用1/3的CPU時間片,或者1/5的時間片。對於CPU資源劃分和調度的探討,可參考以下幾個鏈接:
https://issues.apache.org/jira/browse/YARN-1089
https://issues.apache.org/jira/browse/YARN-1024
Hadoop 新特性、改進、優化和Bug分析系列5:YARN-3
本文彙總了幾個hadoop yarn中常見問題以及解決方案,注意,本文介紹解決方案適用於hadoop 2.2.0以及以上版本。
(1) 默認情況下,各個節點的負載不均衡(任務數目不同),有的節點很多任務在跑,有的沒有任務,怎樣讓各個節點任務數目儘可能均衡呢?
答: 默認情況下,資源調度器處於批調度模式下,即一個心跳會儘可能多的分配任務,這樣,優先發送心跳過來的節點將會把任務領光(前提:任務數目遠小於集羣可以同時運行的任務數量),爲了避免該情況發生,可以按照以下說明配置參數:
如果採用的是fair scheduler,可在yarn-site.xml中,將參數yarn.scheduler.fair.max.assign設置爲1(默認是-1,)
如果採用的是capacity scheduler(默認調度器),則不能配置,目前該調度器不帶負載均衡之類的功能。
當然,從hadoop集羣利用率角度看,該問題不算問題,因爲一般情況下,用戶任務數目要遠遠大於集羣的併發處理能力的,也就是說,通常情況下,集羣時刻處於忙碌狀態,沒有節點一直空閒着。
(2)某個節點上任務數目太多,資源利用率太高,怎麼控制一個節點上的任務數目?
答:一個節點上運行的任務數目主要由兩個因素決定,一個是NodeManager可使用的資源總量,一個是單個任務的資源需求量,比如一個NodeManager上可用資源爲8 GB內存,8 cpu,單個任務資源需求量爲1 GB內存,1cpu,則該節點最多運行8個任務。
NodeManager上可用資源是由管理員在配置文件yarn-site.xml中配置的,相關參數如下:
yarn.nodemanager.resource.memory-mb:總的可用物理內存量,默認是8096
yarn.nodemanager.resource.cpu-vcores:總的可用CPU數目,默認是8
對於MapReduce而言,每個作業的任務資源量可通過以下參數設置:
mapreduce.map.memory.mb:物理內存量,默認是1024
mapreduce.map.cpu.vcores:CPU數目,默認是1
注:以上這些配置屬性的詳細介紹可參考文章:Hadoop YARN配置參數剖析(1)—RM與NM相關參數。
默認情況,各個調度器只會對內存資源進行調度,不會考慮CPU資源,你需要在調度器配置文件中進行相關設置,具體可參考文章:Hadoop YARN配置參數剖析(4)—Fair Scheduler相關參數和Hadoop YARN配置參數剖析(5)—Capacity Scheduler相關參數。
(3)如何設置單個任務佔用的內存量和CPU數目?
答:對於MapReduce而言,每個作業的任務資源量可通過以下參數設置:
mapreduce.map.memory.mb:物理內存量,默認是1024
mapreduce.map.cpu.vcores:CPU數目,默認是1
需要注意的是,默認情況,各個調度器只會對內存資源進行調度,不會考慮CPU資源,你需要在調度器配置文件中進行相關設置。
(4) 用戶給任務設置的內存量爲1000MB,爲何最終分配的內存卻是1024MB?
答:爲了易於管理資源和調度資源,Hadoop YARN內置了資源規整化算法,它規定了最小可申請資源量、最大可申請資源量和資源規整化因子,如果應用程序申請的資源量小於最小可申請資源量,則YARN會將其大小改爲最小可申請量,也就是說,應用程序獲得資源不會小於自己申請的資源,但也不一定相等;如果應用程序申請的資源量大於最大可申請資源量,則會拋出異常,無法申請成功;規整化因子是用來規整化應用程序資源的,應用程序申請的資源如果不是該因子的整數倍,則將被修改爲最小的整數倍對應的值,公式爲ceil(a/b)*b,其中a是應用程序申請的資源,b爲規整化因子。
以上介紹的參數需在yarn-site.xml中設置,相關參數如下:
yarn.scheduler.minimum-allocation-mb:最小可申請內存量,默認是1024
yarn.scheduler.minimum-allocation-vcores:最小可申請CPU數,默認是1
yarn.scheduler.maximum-allocation-mb:最大可申請內存量,默認是8096
yarn.scheduler.maximum-allocation-vcores:最大可申請CPU數,默認是4
對於規整化因子,不同調度器不同,具體如下:
FIFO和Capacity Scheduler,規整化因子等於最小可申請資源量,不可單獨配置。
Fair Scheduler:規整化因子通過參數yarn.scheduler.increment-allocation-mb和yarn.scheduler.increment-allocation-vcores設置,默認是1024和1。
通過以上介紹可知,應用程序申請到資源量可能大於資源申請的資源量,比如YARN的最小可申請資源內存量爲1024,規整因子是1024,如果一個應用程序申請1500內存,則會得到2048內存,如果規整因子是512,則得到1536內存。
(5)我們使用的是Fairscheduler,配置了多個隊列,當用戶提交一個作業,指定的隊列不存在時,Fair Scheduler會自動創建一個新隊列而不是報錯(比如報錯:隊列XXX不存在),如何避免這種情況發生?
答:在yarn-site.xml中設置yarn.scheduler.fair.allow-undeclared-pools,將它的值配置爲false(默認是true)。
(6)使用Hadoop 2.0過程中,遇到了錯誤,怎樣排查錯誤?
答:從hadoop 日誌入手,Hadoop日誌存放位置可參考我這篇文章:Hadoop日誌到底存在哪裏?
前言:hadoop2.x版本和hadoop1.x版本的一個區別就是:hadoop1.x中負責資源和作業調度的是MapReduce,hadoop2.x版本後,MapReduce只專注於計算,資源和作業的調度由YARN來負責。Container是YARN裏面資源分配的基本單位,具有一定的內存以及CPU資源。我們的應用在工作的時候,需要消耗內存和CPU,故當YARN收到application申請,則會根據application申請的資源,分配Container。
在YARN的NodeManager節點上,會將機器的CPU和內存的一定值抽離出來,抽離成虛擬的值,然後這些虛擬的值在根據配置組成多個Container,當application提出申請時,就會分配相應的Container資源。關於默認值我們可以查看官網,如下表所示。
參數 默認值
yarn.nodemanager.resource.memory-mb
-1
yarn.nodemanager.resource.cpu-vcores
-1
yarn.scheduler.minimum-allocation-mb
1024MB
yarn.scheduler.maximum-allocation-mb
8192MB
yarn.scheduler.minimum-allocation-vcores
1
yarn.scheduler.maximum-allocation-vcores
4
內存配置
yarn.nodemanager.resource.memory-mb默認值爲-1,代表着YARN的NodeManager佔總內存的80%。也就是說加入我們的機器爲64GB內存,出去非YARN進程需要的20%內存,我們大概需要64*0.8≈51GB,在分配的時候,單個任務可以申請的默認最小內存爲1G,任務量大的話可最大提高到8GB。
在生產場景中,簡單的配置,一般情況下:yarn.nodemanager.resource.memory-mb直接設置成我們需要的值,且要是最大和最小內存需求的整數倍;(一般Container容器中最小內存爲4G,最大內存爲16G)
假如:64GB的機器內存,我們有51GB的內存可用於NodeManager分配,根據上面的介紹,我們可以直接將yarn.nodemanager.resource.memory-mb值爲48GB,然後容器最小內存爲4GB,最大內存爲16GB,也就是在當前的NodeManager節點下,我們最多可以有12個容器,最少可以有3個容器。
CPU配置
此處的CPU指的是虛擬的CPU(CPU virtual core),之所以產生虛擬CPU(CPU vCore)這一概念,是因爲物理CPU的處理能力的差異,爲平衡這種差異,就引入這一概念。
yarn.nodemanager.resource.cpu-vcores表示能夠分配給Container的CPU核數,默認配置爲-1,代表值爲8個虛擬CPU,推薦該值的設置和物理CPU的核數數量相同,若不夠,則需要調小該值。
yarn.scheduler.minimum-allocation-vcores的默認值爲1,表示每個Container容器在處理任務的時候可申請的最少CPU個數爲1個。
yarn.scheduler.maximum-allocation-vcores的默認值爲4,表示每個Container容器在處理任務的時候可申請的最大CPU個數爲4個。
PS:以上內容是小編我學習的理解,以上所示的參數爲配置過程中基本的參數,如果想配置更爲合理,資源利用率更高,可參考小編轉載的兩篇文章,初學者,如有錯誤請指出,謝謝。
YARN和MapReduce的內存配置優化
YARN的memory和CPU配置詳解