使用 hadoop streaming 編程的幾點經(jīng)驗和教訓(xùn)

hadoop streaming 是 hadoop 的一個多語言編程框架。關(guān)于 streaming 的使用方法可以參見 streaming 的官方文檔。一些比較高級的用法,例如加載詞典,使用計數(shù)器等,也可以在網(wǎng)上找到答案。下面是在使用 streaming 的時候踩到的一些坑,記錄一下。

1,生成本地的 tmp file

hadoop streaming 工作的時候會將要上傳的文件打包并上傳。在客戶端機器上,hadoop client 會將 -file 選項指定的文件拷貝到某個臨時目錄下,并且進行打包程序。所以,要求當(dāng)前用戶需要對這個臨時目錄具有寫權(quán)限。常常遇到的錯誤是,當(dāng)前用戶對這個目錄沒有寫權(quán)限,在提交任務(wù)的時候會報告如下的錯誤:

Exception in thread "main" java.io.IOException: permission denied
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createTempFile(File.java:1879)
at org.apache.hadoop.util.RunJar.main(RunJar.java:115)

這個臨時目錄一般在hadoop 配置文件中的 core-site.xml 和 mapred-site.xml 中指定。一般來說,保證hadoop.tmp.dirmapred.temp.dir所指向的目錄具有寫權(quán)限就足夠了。如果不想修改 core-site.xml 和 mapred-site.xml,可以在提交 streaming job 的時候通過-D選項來指定:

hadoop jar hadoop/contrib/streaming/hadoop-streaming-1.2.0-w1.2.0.jar \
    -Dhadoop.tmp.dir=~/tmp/ \
    -Dmapred.temp.dir=~/tmp/ \
    -mapper "cat"
    -reducer "wc"
    ....

2,多路輸出并不是在每個版本都可用。

hadoop streaming 中 reducer 的輸出文件類似:${outputDir}/part-******,其中 ***** 是 reducer 任務(wù)的任務(wù)號。但有的時候我們希望 reducer 能夠輸出到多路文件,例如,對于文件符合某個條件的,輸出到 part-*****-A,其余的輸出到 part-*****-B。

hadoop-v2-u7 的版本為 streaming 引入了兩個多路輸出的插件:SuffixMultipleTextOutputFormatSuffixMultipleSequenceFileOutputFormat。如果要直接使用這兩個插件,需要保證客戶端和服務(wù)器上的 hadoop 版本均為 hadoop-v2-u7 或者更高。使用這兩個插件的教程可以參見hadoop streaming實戰(zhàn):多路輸出。
需要特別注意的一點是:很多 hadoop 發(fā)行版,即使是最近的發(fā)行版,也未必有這兩個插件(比如 cloudera 的發(fā)行版——當(dāng)然也許是我的版本還不夠高)。確定有沒有這兩個插件的一種方法是看一下這個發(fā)行版的 API 文檔有沒有 org.apache.hadoop.mapred.lib.SuffixMultipleTextOutputFormat 這個類即可(或者直接查看 HADOOP_CLASSPATH)。
如果沒有這個類,需要自己定制一個 MultipleTextOutputFormat(用java)。定制的方法可以參考hadoop多路輸出。

3,/etc/fstab 為 noexec 掛載導(dǎo)致 permission denied

如果 streaming 的 mapper和 reducer 使用的是二進制文件,那么在 mapper 和 reducer 中常常需要這樣調(diào)用:

hadoop jar hadoop/contrib/streaming/hadoop-streaming-1.2.0-w1.2.0.jar \
    -Dhadoop.tmp.dir=~/tmp/ \
    -Dmapred.temp.dir=~/tmp/ \
    -mapper "./mymapper" \
    -reducer "./myreducer" \
    -file "./mymapper" \
    -file "./myreducer" \
    ....

不幸的是,很多時候這樣調(diào)用的時候往往會出現(xiàn)如下的錯誤:

Caused by: java.io.IOException: java.io.IOException: error=13, Permission denied
at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:453)
... 24 more

這個往往是因為,streaming 需要把二進制文件分發(fā)到每臺節(jié)點機器上,創(chuàng)建一個臨時目錄,把二進制文件放到這個臨時目錄里然后開始運行。這個臨時目錄一般在 hadoop 的數(shù)據(jù)磁盤上,通過 /etc/fstab 掛在到計算借點的機器,而很多時候為了安全起見,這個掛載常常指定了 noexec 的屬性:

/home/disk4 ext4 noexec,nosuid,noatime 1 2 UUID="0cbe17e7-4c00-4409-824c-d84e6a80fb5d" /home/disk5 ext4

解決這個問題的方法有:

  • 刪除 noexec 屬性;
  • 使用一個 shell 腳本包裝一個 shell 腳本先將二進制文件拷貝到 /tmp 等目錄,然后再執(zhí)行:
#!/bin/sh
cp ./mymapper /tmp/
/tmp/mymapper

然后指定--mapper "sh mapper.sh"來提交任務(wù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容