在Hadoop雲端環境執行程式時,
主要是將程式先包裹為一個JAR檔後,由Master 將其做為Task送出到各個node進行處理,
然而當系統較為複雜時,程式內引用的處理程序往往更為繁雜,
以生物資訊的案例來說,
一個專案中可能會需要用到如:連結遠端特定服務的library ( Ex:BLAST) , XML 的Library (Ex: JDOM) , 網路連結套件 (Ex: httpclient), WSDL, SAAJ …. 等許許多多的外部函式庫。
這狀況若以Web Service 來說並不會造成問題,
因為Netbeans 會自動Deploy 成一個 war檔進行部署。
但在一般的專案中,
Netbeans只會將專案本身包為 JAR檔,其餘外部的函式( 如引入在 /lib/下的外部jar檔)
在build後並不會包入JAR中,而僅是存放在dist/中的lib/目錄下。
這在平常或許沒什麼太大問題,
只要設定classpath或放到公用java classpath (ext/lib)中即可。
但在雲端環境中,由於JAR是做為Task傳送到不同的node server執行,
除非是每個node都預先存放好 library,否則在執行時便會因為僅將專案JAR檔送出,
造成 node server找不到外部library 而引發ClassNotFoundException導致task falue 。
解決上述問題的方式,有以下幾種方法:
- 將library放入各node Server的共用函式資料夾
- 將外部涵式解開JAR後,將package複製到自己的專案內,再令其重新build包裹在一起
- 直接將JAR檔包進JAR中
然而在雲端環境中,若要逐一對node server預先設定外部library,
不只耗時費工 (node server可能高達百臺),更有可能因為外部server而無法進行設定。
以上作法最便利的便是第三種方式:將外部的JAR包入專案的JAR中
此方法類似 Eclipse中的 “Fat Jar” plugin ,可以將外部的JAR直接包裝進JAR中,
而 Netbeans的作法則僅需修改ANT的build.xml便可達成。
唯編輯ANT的方式較為複雜,以下推薦一個網友分享的方式讓大家參考。
( From: Fat JARs out of NetBeans – by Joshua Born )
作法如下 (以下採用 Netbeans IDE 6.9.1):
- 1. 將外部函式匯入 lib
- 2. 點選專案視窗的Files分頁
- 3. 開啟專案中的build.xml檔,並於<project> </project> 範圍內加入以下Tag,並存檔
<target name="-unjar-and-copy-lib-jars">
<unjar dest="${build.classes.dir}">
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<patternset>
<exclude name="META-INF/**"/>
<exclude name="/*"/>
</patternset>
</unjar>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar,-unjar-and-copy-lib-jars" name="fat-jar">
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<jar destfile="${dist.jar}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
</manifest>
</jar>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target depends="clean,fat-jar" name="clean-and-fat-jar"/>
- 4. build.xml修改完成後,在該檔案上按右鍵選[Run Target] –> [Other Targets] ,當中便會出現[fat-jar] , [clean-and-fat-jar],執行[fat-jar]後即可在dist中編出單一個JAR檔
- 5. 隨後便可以將該JAR檔做為Hadoop Job執行 ( Hadoop之Netbeans開發環境設定請見:『Hadoop with Netbeans 雲端開發環境』一文)
透過上述的方法便可以很輕鬆的進行JAR包裝,
這對想要移植過去的JAVA專案至雲端應用上是非常有幫助的,
不過這個作法有許多缺點,
最大的問題是包裹後的JAR檔相當肥大(檔案大小),
因此在Master Server進行task分派時勢必會造成流量的增加,
以單JAR 5mb來說,
若有100個task運行於100個node,則一個job造成的流量便會超過500mb,
這對系統來說會是非常大的負擔,尤其是node server不在鄰近區域時更會影響,
因此,盡可能的精減外部Library的使用,
並且將未用到的library 刪除,更甚至用解JAR的方式來取出僅需要的部份,
這樣的方式便可以減少傳輸流量的暴增,降低系統負擔。
BP 2011.06.10
相關文章:
留言
張貼留言