談談hadoop日誌限制的問題

一、概述

hadoop中主要有三類的MR任務:普通javaMR、streaming、pipes。其中streaming與pipes本質是差不多的,都會創建一個新的進程(除child外的),streaming是基於in、out、err標準輸入輸出來傳遞數據的,pipes則是通過socket來傳遞數據的。要查詢他們的具體內容,請google去吧。本文主要講述他們的日誌限制問題。由於他們都是用戶自定義的程序,所以往往認爲是不可靠的,特別是對磁盤空間的利用,最嚴重的表現就是寫入大量的日誌直接把磁盤打滿,這樣TaskTracker就相當於罷工了。

二、分析

在配置文件中有一個配置項mapred.userlog.limit.kb,默認是0,就是限制用戶的日誌大小的作用,當配置爲10kb的時候,那麼任務當寫到10k左右的日誌的時候就會不再寫入日誌了。這個參數在三類任務中還是有點差別的。先說出他們之間的關係:

類型\日誌 stdout stderr syslog
普通javaMR 官方無限制,阿里巴巴用mapred.systemlog.limit.kb限制超出後任務報錯 官方無限制,阿里巴巴用mapred.systemlog.limit.kb限制超出後任務報錯 用官方mapred.userlog.limit.kb,且是在任務結束時打印日誌,日誌內容爲tail -f len部分。len是mapred.userlog.limit.kb*1024/100取整。超出後不報錯。
streaming 無日誌 官方無限制,阿里巴巴用mapred.systemlog.limit.kb,任務完成後打印日誌,內容不超過mapred.systemlog.limit.kb,內容是head -c  mapred.systemlog.limit.kb*1024,超出後不報錯。 用官方mapred.userlog.limit.kb,且是在任務結束時打印日誌,日誌內容爲tail -f len部分。len是mapred.userlog.limit.kb*1024/100取整。超出後不報錯。
pipes 用官方mapred.userlog.limit.kb,任務完成後打印日誌,內容不超過mapred.userlog.limit.kb,內容就是 tail -c mapred.userlog.limit.kb*1024,超出後不報錯。 用官方mapred.userlog.limit.kb,任務完成後打印日誌,內容不超過mapred.userlog.limit.kb,內容就是 tail -c mapred.userlog.limit.kb*1024,超出後不報錯。 用官方mapred.userlog.limit.kb,且是在任務結束時打印日誌,日誌內容爲tail -f len部分。len是mapred.userlog.limit.kb*1024/100取整。超出後不報錯。


看起來還是比較亂的,還是簡單講下各自的原理吧。我們可以看出,先拋開阿里巴巴自定義的方式不講,官方是用mapred.userlog.limit.kb來限制日誌的大小的。

主要有三大塊:

syslog的所有情況:我們可以看出syslog日誌,說白了就是log4j的日誌,hadoop定義了一個TaskLogAppender,在task中就是用TaskLogAppender來做手腳的。代碼路徑:http://svn.apache.org/repos/asf/hadoop/common/tags/release-0.19.1/src/mapred/org/apache/hadoop/mapred/TaskLogAppender.java,他就定義了一個隊列Queue<LoggingEvent>,當新產生一個LoggingEvent就放到Queue中,等child主進程運行到finally時調用LogManager.shutdown(),TaskLogAppender close的時候一次性寫到磁盤。

streaming的stderr情況:命令是直接用jdk的Process來啓動的,啓動後把in,out,err的流關聯到對象OutputStream及InputStream中,後用MROutputThread線程處理out流,用MRErrorThread線程處理err流。

具體的過程:MROutputThread中OutputCollector.collect會收集out的結果,而MRErrorThread中,結果直接被System.err.println輸出。代碼在:http://svn.apache.org/repos/asf/hadoop/common/tags/release-0.19.1/src/contrib/streaming/src/java/org/apache/hadoop/streaming/PipeMapRed.java中。

pipes的stdout及stderr情況:如果不熟悉例子就請訪問http://wiki.apache.org/hadoop/C++WordCount。其實是用了Application封裝Process,這個不同於streaming的情況。大致的啓動命令爲:

Bash -C ('/Tmp/Hadoop-Dragon.Caol/Mapred/Local/Tasktracker/Archive/-5349814786282004457/h1/examples/bin/wordcount-simple'  < /dev/null  | tail -c 102400 >> /home/dragon.caol/hadoop-0.19.1-dc/bin/../logs/userlogs/job_201210241401_0001/attempt_201210241401_0001_m_000000_0/stdout ; exit $PIPESTATUS ) 2>&1 | tail -c 102400 >> /home/dragon.caol/hadoop-0.19.1-dc/bin/../logs/userlogs/job_201210241401_0001/attempt_201210241401_0001_m_000000_0/stderr ; exit $PIPESTATUS
這個命令還是比較複雜的,大致的意思就是執行wordcount-simple,把標準正確輸出到stdout文件,把標準錯誤輸出到stderr文件。我們看到在命令中有tail -c 102400的字樣,說明並不是全部打印。

阿里巴巴版本做的一個限制:這個是在system.out/err打印日誌時起作用的,具體的做法就是對out/err重定向,再數數,如果超過mapred.systemlog.limit.kb*1024,則直接拋異常。所以就會使child直接掛掉。但是在streaming中由於是用MRErrorThread線程做這件事情,也沒有做特別干涉main線程,所以不會對main線程有影響。

三、總結

1、我們並不建議把mapred.userlog.limit.kb設置較大,如果較大可能會引起內存溢出。

2、阿里巴巴在改造的過程中直接拋出異常,這個也是我們不建議用戶打印較多的日誌。

3、我們經常發現一些程序,如:perl會打印一些調試的信息,如果不做限制,這些信息最終會把磁盤打滿。由於調度器會重新調度,這種錯誤可能會引起較多的tasktracker罷工。

四、聲明

文章可能會重新編輯,如果想瀏覽最新內容請訪問原創博客:http://blog.csdn.net/bxyz1203/article/details/8107125。由於作者個人知識面有限,如果描述有錯誤或者遺留之處敬請諒解,再歡迎指出,我們共同進步。

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