新聞中心
牢記以下五個(gè)步驟可以為你減少很多頭痛的問(wèn)題并且避免Java堆空間錯(cuò)誤。

發(fā)展壯大離不開(kāi)廣大客戶長(zhǎng)期以來(lái)的信賴與支持,我們將始終秉承“誠(chéng)信為本、服務(wù)至上”的服務(wù)理念,堅(jiān)持“二合一”的優(yōu)良服務(wù)模式,真誠(chéng)服務(wù)每家企業(yè),認(rèn)真做好每個(gè)細(xì)節(jié),不斷完善自我,成就企業(yè),實(shí)現(xiàn)共贏。行業(yè)涉及成都石雕等,在網(wǎng)站建設(shè)、成都全網(wǎng)營(yíng)銷、WAP手機(jī)網(wǎng)站、VI設(shè)計(jì)、軟件開(kāi)發(fā)等項(xiàng)目上具有豐富的設(shè)計(jì)經(jīng)驗(yàn)。
- 通過(guò)計(jì)算預(yù)期的內(nèi)存消耗。
- 檢查JVM是否有足夠的可用空間。
- 檢查JVM的設(shè)置是否正確。
- 限制節(jié)點(diǎn)使用交換空間和內(nèi)存分頁(yè)。
- 設(shè)置實(shí)例slot數(shù)量小于JobTracker web GUI計(jì)算的數(shù)值。
譯者注:slot :slot不是CPU的Core,也不是memory chip,它是一個(gè)邏輯概念,一個(gè)節(jié)點(diǎn)的slot的數(shù)量用來(lái)表示某個(gè)節(jié)點(diǎn)的資源的容量或者說(shuō)是能力的大小,因而slot是 Hadoop的資源單位。詳見(jiàn)這里。
在這篇博文里,我將詳細(xì)講解每個(gè)步驟,幫助大家更好地理解并正確管理實(shí)例(task attempt)內(nèi)存。
譯者注:實(shí)例(task attempt) :這個(gè)詞在官方文檔中找到了解釋: “Each task attempt is one particular instance of a Map or Reduce Task identified by its TaskID”。
理解怎樣管理實(shí)例內(nèi)存是很重要的,這樣可以避免Java堆空間錯(cuò)誤。當(dāng)運(yùn)行 map/reduce 作業(yè)(Job)時(shí),你可能會(huì)看到實(shí)例出現(xiàn)這樣的錯(cuò)誤:
- 13/09/20 08:50:56 INFO mapred.JobClient: Task Id : attempt_201309200652_0003_m_000000_0, Status : FAILED on node node1
- Error: Java heap space
當(dāng)試圖申請(qǐng)一個(gè)超過(guò)Java虛擬機(jī)(JVM)設(shè)置的最大內(nèi)存限制時(shí)就會(huì)發(fā)生這個(gè)錯(cuò)誤。
避免Java堆空間錯(cuò)誤的第一步是了解你的map和reduce任務(wù)的內(nèi)存需求,以便于你啟動(dòng)一個(gè)JVM時(shí)設(shè)置了適當(dāng)內(nèi)存限制。
例如,hadoop-0.20.2-dev-examples.jar中的wordcount 功能。 不管處理什么數(shù)據(jù),map 任務(wù)都不需要很多內(nèi)存。唯一需要很多內(nèi)存的就是在加載運(yùn)行所需的函數(shù)庫(kù)的時(shí)候。當(dāng)使用默認(rèn)附帶MapR包的wordcount功能時(shí),512MB的內(nèi)存對(duì)于實(shí)例JVM是綽綽有余了。如果你打算運(yùn)行我們提供的Hadoop示例,可以嘗試將map實(shí)例JVM的內(nèi)存限制設(shè)為512MB。
如果你知道自己的map實(shí)例需要多少內(nèi)存(在本例中是512MB), 那么下一步啟動(dòng)設(shè)置好JVM內(nèi)存。該實(shí)例在JVM中的內(nèi)存是由TaskTracker為Map/Reduce作業(yè)處理數(shù)據(jù)而設(shè)定的。 TaskTracker設(shè)定的限制可能有兩個(gè)來(lái)源:要么是用戶提交作業(yè)時(shí)指定了內(nèi)存大小作為該作業(yè)配置對(duì)象的一部分,或者是TaskTracker產(chǎn)生了 默認(rèn)內(nèi)存大小的JVM。
mapred.map.child.java.opts屬性被用來(lái)為TaskTracker 啟動(dòng)JVM和執(zhí)行map任務(wù)的參數(shù)(在reduce任務(wù)中也有個(gè)類似的屬性)。如果mapred.map.child.java.opts屬性被設(shè)置成“-Xmx512m”,那么map實(shí)例JVMs會(huì)有512MB的內(nèi)存限制。相反的,如果-Xmx沒(méi)有通過(guò)配置屬性去指定一個(gè)數(shù)值的話,那么 每個(gè)TaskTracker將會(huì)為啟動(dòng)JVM計(jì)算一個(gè)默認(rèn)的內(nèi)存限制。該限制是基于TaskTracker為map/reduce task slot分配的數(shù)量所決定的,并且TaskTracker分配給Map/Reduce總內(nèi)存不能超過(guò)系統(tǒng)限制。
TaskTracker為map/reduce實(shí)例分配的slot數(shù)量在TaskTracker啟動(dòng)時(shí)就設(shè)定好了。通過(guò)每個(gè)節(jié)點(diǎn)上mapred-site.xml文件中兩個(gè)參數(shù)進(jìn)行控制的:
- mapred.tasktracker.map.tasks.maximum
- mapred.tasktracker.reduce.tasks.maximum
設(shè)置這些默認(rèn)值的規(guī)則是基于節(jié)點(diǎn)上CPU核心的數(shù)量。不過(guò)你可以下面兩個(gè)方法來(lái)重載參數(shù):
- 修改mapred-site.xml文件設(shè)定一個(gè)固定的slots數(shù)值。
- 使用自定義規(guī)則。
在系統(tǒng)中,TaskTracker map/reduce實(shí)例內(nèi)存限制是在TaskTracker進(jìn)程啟動(dòng)時(shí)設(shè)定的。有兩個(gè)地方可以設(shè)置內(nèi)存限制。首先在Hadoop conf目錄下的hadoop-env.sh腳本中可以顯式的設(shè)置,你可以添加下面這行來(lái)指定內(nèi)存限制:
- export HADOOP_HEAPSIZE=2000
這行命令限制了節(jié)點(diǎn)上的所有實(shí)例JVM總共可以使用2000MB的內(nèi)存。如果沒(méi)有在hadoop-env.sh文件中指定 HADOOP_HEAPSIZE這個(gè)參數(shù),那么當(dāng)MapR warden service啟動(dòng)TaskTracker時(shí)會(huì)對(duì)內(nèi)存進(jìn)行限制。 warden service會(huì)基于節(jié)點(diǎn)上物理內(nèi)存的數(shù)量減去服務(wù)運(yùn)行中已經(jīng)占用的內(nèi)存數(shù)量得出限制的大小。如果你去看看warden.conf你會(huì)看到像這樣的一些屬性:
- service.command.mfs.heapsize.percent=20
- service.command.mfs.heapsize.min=512
這個(gè)例子表示,warden占用分配給MFS服務(wù)節(jié)點(diǎn)的20%物理內(nèi)存或最低512MB(512MB<20%的物理內(nèi)存的情況下)。如果你考慮所有服務(wù)都配置在一個(gè)節(jié)點(diǎn)上運(yùn)行的話,你要考慮下在 warden.conf中指定下內(nèi)存分配。你應(yīng)該能明確多少內(nèi)存用于服務(wù)配置(還要為系統(tǒng)正常運(yùn)行預(yù)留內(nèi)存)。剩下的內(nèi)存就是TaskTracker為并發(fā)運(yùn)行實(shí)例設(shè)置的內(nèi)存限制了。
例如,假設(shè)你在一個(gè)節(jié)點(diǎn)上安裝運(yùn)行ZooKeeper、CLDB、MFS、JobTracker、TaskTracker、NFS、the GUI、HBase Master 和HBase RegionServer。這么多的服務(wù)運(yùn)行在一個(gè)節(jié)點(diǎn)上,而且每個(gè)服務(wù)都需要內(nèi)存,所以warden會(huì)將內(nèi)存按照百分比分配給每個(gè)服務(wù),剩下的將會(huì)分配 給節(jié)點(diǎn)上的map/reduce 實(shí)例。如果你分配給這些服務(wù)總共60%還有5%為系統(tǒng)預(yù)留,那么就還有35%分給節(jié)點(diǎn)上的map/reduce實(shí)例。如果這個(gè)節(jié)點(diǎn)有10G的內(nèi)存,將會(huì)有3.5G分給 map/reduce 任務(wù)。如果你有 6個(gè)map slot和4個(gè)reduce slot。如果內(nèi)存是平均分配的,最終每個(gè)JVM的內(nèi)存限制為350MB。如果你需要512MB內(nèi)存來(lái)運(yùn)行你的map任務(wù),那么默認(rèn)設(shè)置的情況下是不會(huì)運(yùn)行的,你會(huì)遇到Java堆空間錯(cuò)誤。
當(dāng)管理實(shí)例內(nèi)存的時(shí)候會(huì)意識(shí)到還有其它問(wèn)題。不要強(qiáng)制節(jié)點(diǎn)去使用大量的交換空間(swap space)或者觸發(fā)頻繁內(nèi)存分頁(yè)讀寫磁盤。如果你通過(guò)顯式的在mapred.map.child.java.opts設(shè)置“-Xmx500m”來(lái)改變提交的作業(yè),將會(huì)重寫安全的內(nèi)存限制。但實(shí)際上你并沒(méi)有額外的物理內(nèi)存。雖然 map/reduce 實(shí)例仍能啟動(dòng),但是會(huì)強(qiáng)制使用大量的交換空間,而且無(wú)法依賴內(nèi)核的OOM killer或者其他的方法來(lái)防止這種情況發(fā)生。如果真的發(fā)生這種情況,無(wú)法指望節(jié)點(diǎn)啟動(dòng)大量分頁(yè)來(lái)迅速恢復(fù)。如果只是增加了實(shí)例的JVM內(nèi)存,同時(shí)繼續(xù)在節(jié)點(diǎn)上啟動(dòng)相同數(shù)量的實(shí)例。你會(huì)申請(qǐng)更多的內(nèi)存,需要注意不要超額申請(qǐng)。如果超額申請(qǐng)?zhí)嗟脑?,?huì)導(dǎo)致大量的分頁(yè),這樣節(jié)點(diǎn)可能會(huì)被掛 起再也無(wú)法恢復(fù)。除非重啟電源。
所以如果你給每個(gè)實(shí)例JVM增加內(nèi)存的話,需要通過(guò)TaskTrackers來(lái)減少分配給map/reduce task slot數(shù)量。
這是一個(gè)很復(fù)雜的情況,因?yàn)槿绻阍诩荷喜l(fā)執(zhí)行不同的作業(yè),可能來(lái)自一個(gè)作業(yè)(JobA)的實(shí)例需要大量的內(nèi)存,來(lái)自另外一個(gè)作業(yè)(JobB)的實(shí)例只需要很少的內(nèi)存。因此,如果你減少map/reduce slot的數(shù)量,會(huì)發(fā)現(xiàn)會(huì)有足夠的內(nèi)存來(lái)運(yùn)行來(lái)自JobB任務(wù)(task)。但是卻沒(méi)有足夠的內(nèi)存提供給JobA。所以關(guān)鍵就是找到一個(gè)平衡點(diǎn),一個(gè)可以允許進(jìn)行一些超額申請(qǐng)卻不會(huì)導(dǎo)致節(jié)點(diǎn)被掛起的平衡點(diǎn)。
為了協(xié)助這個(gè)任務(wù),TaskTracker 將會(huì)著眼于當(dāng)前所有在運(yùn)行的 map/reduce tasks 所使用的內(nèi)存數(shù)量。不是只看這些任務(wù)的最大內(nèi)存限制,而是所有運(yùn)行中的實(shí)例實(shí)際利用的內(nèi)存總數(shù)。當(dāng)消耗的內(nèi)存達(dá)到一定級(jí)別,TaskTracker 會(huì)殺死一些運(yùn)行的實(shí)例來(lái)釋放內(nèi)存,以便其他的實(shí)例能正常執(zhí)行完并且不會(huì)造成節(jié)點(diǎn)上的分頁(yè)過(guò)多。
舉個(gè)例子,如果你想在一個(gè)小型的集群或者單一節(jié)點(diǎn)上運(yùn)行wordcount示例,碰到“Java堆空間”錯(cuò)誤,最簡(jiǎn)單最快的解決方法就是通過(guò)編輯/opt/mapr/hadoop/hadoop-0.20.2/conf/mapred-site.xml中的設(shè)置來(lái)減少 map/reduce 實(shí)例 slot的數(shù)量:
- mapred.tasktracker.map.tasks.maximum
- mapred.tasktracker.reduce.tasks.maximum
將實(shí)例的slot的數(shù)量設(shè)置為小于當(dāng)前計(jì)算結(jié)果是非常重要的。當(dāng)前計(jì)算的數(shù)量可以通過(guò)進(jìn)入JobTracker web界面來(lái)確定。例如,如果你有一個(gè)TaskTracker ,顯示它有6個(gè)mpa slot和4個(gè) reduce slot,那么你應(yīng)該設(shè)置 3個(gè)map slot、2個(gè) reduce slot。然后通過(guò)下面這行命令重啟節(jié)點(diǎn)上的TaskTracker進(jìn)程:
- maprcli node services -nodes -tasktracker restart
減少slot的數(shù)量重新啟動(dòng)后,重新提交wordcount作業(yè)。如果沒(méi)有額外內(nèi)存申請(qǐng),每個(gè)實(shí)例、JVM都會(huì)分配到更多的內(nèi)存。這是一個(gè)安全的解決方法,節(jié)點(diǎn)不會(huì)產(chǎn)生大量分頁(yè)。這是一種簡(jiǎn)單的解決方案,不需要大量計(jì)算內(nèi)存。這也是快速的方法,只需要編輯下配置文件并重啟下服務(wù)就好了。
為了避免Java堆空間錯(cuò)誤,記住下面這些步驟:
- 估算你的實(shí)例需要消耗多少內(nèi)存。
- 確保TaskTracker 啟動(dòng)你的實(shí)例時(shí),JVM內(nèi)存的限制要大于等于你預(yù)計(jì)的內(nèi)存需求。
- 記住,啟動(dòng)這些JVM是有默認(rèn)設(shè)置的,除非你顯式的重寫過(guò)這些設(shè)置。在CPU核心數(shù)和物理內(nèi)存已經(jīng)平衡并運(yùn)行服務(wù)的節(jié)點(diǎn)上,默認(rèn)設(shè)置并不適用。
- 不要迫使節(jié)點(diǎn)大量的使用交換空間或者頻繁的將內(nèi)存分頁(yè)讀寫到磁盤上。
- 將實(shí)例slot數(shù)量設(shè)置為小于JobTracker web GUI計(jì)算值。
原文鏈接: mapr 翻譯: ImportNew.com - 光光頭去打醬油
譯文鏈接: http://www.importnew.com/14049.html
本文名稱:5步避免Java堆空間錯(cuò)誤
標(biāo)題URL:http://fisionsoft.com.cn/article/cdgphjj.html


咨詢
建站咨詢
