今天在調試mapred streaming指令碼時,發生了非常奇怪的問題:mapred指令碼在被tasktracker調用後總是會隨機的失敗,錯誤資訊如下:
java.lang.RuntimeException: java.lang.NullPointerExceptionat org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:325)at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:545)at org.apache.hadoop.streaming.PipeReducer.reduce(PipeReducer.java:95)at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:518)at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:419)at org.apache.hadoop.mapred.Child$4.run(Child.java:259)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAs(Subject.java:396)at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1059)at org.apache.hadoop.mapred.Child.main(Child.java:253)Caused by: java.lang.NullPointerExceptionat org.apache.hadoop.streaming.PipeMapRed$MRErrorThread.setStatus(PipeMapRed.java:522)at org.apache.hadoop.streaming.PipeMapRed$MRErrorThread.run(PipeMapRed.java:454)
從錯誤資訊中,我們可以知道:錯誤並不是mapred指令碼錯誤導致的,而是在tasktracker初始化mapred指令碼時tasktracker發生了內部錯誤
最初以為是叢集伺服器某些系統資源不夠導致的錯誤,但是查看叢集其他正在啟動並執行任務後,確並沒有發現和上面同樣的問題,其他正在啟動並執行任務完全沒有拋出上面的錯誤。現在可以肯定是我的mapred指令碼的問題,考慮到我再mapred指令碼中使用的redis,而我的redis介面包是我自己在redis-py的基礎上修改而來(redis-py不支援python2.4版本),懷疑是不是redis-py的包引發上述問題,於是屏蔽掉代碼中使用redis模組的代碼,再次運行mapred,結果還是發生了同樣的問題。
沒辦法,只好再仔細對比正常的mapred指令碼和我現在又問題的mapred指令碼之間的差異,發現和正常的mapred指令碼相比,現在的代碼多出了一句向jobtarcker彙報mapred指令碼運行狀態的代碼:
sys.stderr.write("reporter:status:output\n")
雖然理論上這條語句不應該會導致上述奇怪的問題發生,但是還是死馬當活馬醫試試看,屏蔽掉mapred指令碼中的這條代碼,重新運行mapred指令碼,奇蹟發生了,一切正常,沒有任何錯誤發生;重新再加上redis操作的代碼,再次運行mapred指令碼,還是沒有錯誤發生。看來,問題的元兇就是這條向jobtracker彙報狀態的代碼:
sys.stderr.write("reporter:status:output\n")
上述錯誤 應該是tasktracker中的一個小bug,不知道是否有人提交了這個bug?馬上我們的叢集就要升級到hadoop1.0.3,到時候在hadoop1.0上再測試測試