最近在做數據遷移的工作,但是那在使用hue建的工作流,提交任務之后兩個任務,一個是oozie的常駐進程job laucher,還有一個就是真實的任務。action操作的任務。
執行的結果就是這樣的,launcher操作一直停在95%,正真的action操作則一直停在5%這里。然后hue的日志一直在向master發送心跳,也不報錯,就一直卡着。然后網上百度了一圈,說調資源就可以了。但是一直調就是不行,很奇怪。
調着調着還把問題調出來了資源給的太小,然后就oom了。錯誤如下:
Diagnostics: Container [pid=24987,containerID=container_1536566845435_0002_02_000001] is running beyond physical memory limits.
Current usage: 271.2 MB of 256 MB physical memory used; 1.5 GB of 537.6 MB virtual memory used. Killing container.
這里要解釋一下這個錯誤了:
271.2MB: 任務所占的物理內存
256MB 是mapreduce.map.memory.mb 設置的
1.5G 是程序占用的虛擬內存
537.6MB 是mapreduce.map.memory.db 乘以 yarn.nodemanager.vmem-pmem-ratio 得到的
其中yarn.nodemanager.vmem-pmem-ratio 是 虛擬內存和物理內存比例,在yarn-site.xml中設置,默認是2.1, 由於我本地設置的是256, container占用了1.5G的虛擬內存,但是分配給container的卻只有537.6MB。所以kill掉了這個container
這個是由於我們在調整yarn上面的資源的時候,包括map的內存,reduce的內存的時候分配的太小了,導致提交的任務需要的資源集群當中滿足不了,導致內存溢出,然后這個container就爆掉了。然后沒辦法運行。
說到這里我們來看一下yarn當中的資源的配置:
yarn-site.xml yarn.scheduler.minimum-allocation-mb yarn.scheduler.maximum-allocation-mb 說明:單個容器可申請的最小與最大內存,應用在運行申請內存時不能超過最大值,小於最小值則分配最小值,從這個角度看,最小值有點想操作系統中的頁。最小值還有另外一種用途,計算一個節點的最大container數目注:這兩個值一經設定不能動態改變(此處所說的動態改變是指應用運行時)。 默認值:1024/8192 yarn.scheduler.minimum-allocation-vcores yarn.scheduler.maximum-allocation-vcores 參數解釋:單個可申請的最小/最大虛擬CPU個數。比如設置為1和4,則運行MapRedce作業時,每個Task最少可申請1個虛擬CPU,最多可申請4個虛擬CPU。 默認值:1/32 yarn.nodemanager.resource.memory-mb
參數解釋:這個參數的配置是非常重要的,他是每個節點可用的最大內存,RM(resourcemanager)中的兩個值不應該超過此值。此數值可以用於計算container最大數目
下面來看一下這幾個參數之間的關系:
yarn.scheduler.minimum-allocation-mb 和 yarn.scheduler.maximum-allocation-mb 這兩個都是單個的container申請資源的最小和最大值,應用在運行時申請的內存不能超過這個配置項的值。
但是這個配置項是指定一個container的最大的內存,實際分配內存時並不是按照配置項進行分配,這里的配置項配置成和nodemanager的可用內存(yarn.nodemanager.resource.memory-mb)一樣即可,這樣的話,意味着只要節點的nodemanager可用內存哪怕
只有一個container,這個container也可以啟動。(這里其實就是說我們盡量將兩者的值配置相同)。
因為如果配置的參數比nodemanager的可用內存(yarn.nodemanager.resource.memory-mb)小,那么可能出現這個節點總內存即使足夠提供所需內存的,但卻無法啟動container的情況。
這里還要說一點,
yarn.nodemanager.resource.memory-mb 的配置決定了集群當中總的內存大小。截圖如下

我這里配置的是每個節點為1.5G,然后每個節點2核。所以在這里就會出現這樣的情況。我們的集群是三台機器,所以這里的總數就是這樣的。
說到這里我們還需要關心的配置就是我們的map的內存和reduce的內存配置了。另外就是appMaster的配置項的配置。
mapreduce.map.memory.mb
- 指定map任務時申請的內存,是一個精確值,不是范圍值,這就是一個map真實用到內存的值了。
- 這個配置是可以在腳本或代碼中動態申請的,但是取值范圍必須是在container內存大小值之間。
- 即 yarn.scheduler.minimum-allocation-mb < mapreduce.map.memory.mb < yarn.scheduler.maximum-allocation-mb
- 比如在hive中申請:set mapreduce.map.memory.mb=4096;
- 實際上,我們現在大部分腳本在執行前都是動態申請一下的。只要在container大小以內。
遺留問題:
這個值該如何配置。還是說不需要配置,只需要把控container的大小內存,有開發人員根據實際情況申請,
mapreduce.reduce.memory.mb
和map的是對應的,指定reduce任務執行時申請的內存,是一個精確值,不是范圍值。
可以在腳本或者代碼中動態申請,取值范圍必須是在container內存大小值之間。
配置時建議這個值是map的2倍,這個可能是要考慮到多個map后數據可能會有一個reduce處理,根據實際需要來看。
(這說一下,不一定為map的兩倍奧,因為如果你container的大小為1.5G,然后你的map內存為1G,然后你將reduce的大小設置為2G就會報下面的錯誤,所以還是要按照自己的實際情況去定義)
REDUCE capability required is more than the supported max container capability in the cluster. Killing the Job. reduceResourceRequest: <memory:2048, vCores:1> maxContainerCapability:<memory:1536, vCores:2> Job received Kill while in RUNNING state.
yarn.app.mapreduce.am.resource.mb
指定appMaster的運行內存,默認是1.5g。
appMaster也是運行在container中,所以如果修改了yarn.scheduler.maximum-allocation-mb,就要注意修改這個配置
這個值必須小於 yarn.scheduler.maximum-allocation-mb才可以啟動appMaster
至此我的總結就是在改yarn的資源配置的時候,我們首先關系的應該是 yarn.nodemanager.resource.memory-mb 這個配置參數的大小,因為這個定下來之后我們在去定義 yarn.scheduler.maximum-allocation-mb的大小。
從而我們就可以定義map的內存大小,reduce的內存大小隨之就別定義好了。只有這樣我們的集群資源不會出現內存溢出的現象。當內存溢出的時候我們的解決辦法是盡量的調整 mapreduce.map.memory.mb的代表不要讓虛擬內存超過實際的物理內存。
爆出下面這個錯誤(也不要關掉內存檢查機制,因為那樣是治標不治本的。只有調整map的內存才行)
Diagnostics: Container [pid=24987,containerID=container_1536566845435_0002_02_000001] is running beyond physical memory limits.
Current usage: 271.2 MB of 256 MB physical memory used; 1.5 GB of 537.6 MB virtual memory used. Killing container.
我的問題最后解決了,假死的任務啟動了。但是我改了好多遍。來回改這幾個參數。我介紹一下我改的情況:
yarn.scheduler.minimum-allocation-mb 256MB yarn.scheduler.maximum-allocation-mb 1.5GB
yarn.nodemanager.resource.memory-mb 1.5GB
mapreduce.map.memory.mb 1GB
mapreduce.reduce.memory.mb 1GB
yarn.app.mapreduce.am.resource.mb 512MB
改的配置參數大概就這么多。具體的以自己集群當中的實際資源為准去配置就可以了。
