2013年6月29日 星期六

Hadoop Distributed Cache - 如何讓Map Reduce Job 認得 3rd-aprty Libraries



在撰寫Map Reduce Job時,我想 java.lang.ClassNotFoundException 這個問題一定排名前幾名,會發生這個問題的主要原因就是我們在寫Map Reduce Job時,可能會引用到外部 Jar 檔(3rd party Libraries),而運行Map Reduce Job的那一台機器的class path 找不到那個Jar檔而發生的問題。

當遇到這個問題大家一定馬上就會去Goolge找解決方法,而且很容易就會在網路上找到各種解法,但是很多解法你一看就會覺得很骯髒很暴力,下面是排名最常見的解法:

1. 把需要用到的Jar 檔 copy到每一台機器去,並且設定Class Path
其實這些建議都是正確的,但是只適合在開發階段和單機環境,一旦到了真正的叢集運行環境就不能這樣搞了,試想想100台以上的Cluster那不是要Copy到死!?而且一但Jar檔如果要升級和更新,那更是一場災難

2. 透過Hack的招數,寫程式把會用到的外部Jar檔Class Path找出來
太暴力了,直接跳過~:P

3. 最建議的方法是使用Hadoop Distributed Cache

作法如下:

1. 把所需要的Jar檔Copy到Hdfs路徑下
 
# bin/hadoop fs -copyFromLocal mylib.jar /lib/mylib.jar
or
# bin/hadoop fs -put myjar.jar /lib/.

2. 在你的程式裡面設定Distributed Cache 設定
JobConf job = new JobConf();
DistributedCache.addCacheFile(new URI("/lib/mylib.jar#mylib.jar"), job);
DistributedCache.addCacheArchive(new URI("/lib/mylib.jar#mylib2.jar", job);


嗯看起來這樣就可以解決問題了!不過還是不夠方便,因為這時候已經把Lib 的名稱和路徑以及數量 Hard Code在程式裡面了,如果要改路徑怎麼辦?如果Lib要升級該怎麼辦?所以這時候就有請Spring Hadoop 出場~~

真的非常簡單,只要在Spring 的設定裡面加入下面內容,這樣甚至都不用寫在程式裡面,因為透過Spring Hadoop的設定,直接就把這些值寫入Hadoop Configuration 裡面了。


<hdp:cache create-symlink="true">
   <hdp:classpath value="/lib/mylib.jar#mylib.jar" />
   <hdp:classpath value="/lib/mylib.jar#mylib2.jar" />
</hdp:cache>



雖然看起來很簡單的幾行,卻花了好多時間才找到正確的用法,與最方便得設定方式....

深深覺得網路上關於Hadoop的教學資源大多只是極度簡化的範例程式(最常見的就是word count) 但是離開發真實商業應用系統還非常的遠,而且相關的文章更是少的可憐...Orz..


Reference:
[1] Hadoop Distributed Cache tutorial


張貼留言