【轉】Mapreduce部署與第三方依賴包管理


Mapreduce部署是總會涉及到第三方包依賴問題,這些第三方包配置的方式不同,會對mapreduce的部署便捷性有一些影響,有時候還會導致腳本出錯。本文介紹幾種常用的配置方式:

1. HADOOP_CLASSPATH

    在hadoop的相關配置文件中,添加CLASSPATH路徑,那么在hadoop的各個進程啟動時都會載入這些包,因此對於mapreduce-job jar中則不需要額外的引入這些jars,所以mapreduce-job jar會比較小[瘦jar],便於傳輸;但它的問題也比較明顯,如果mapreduce-job中新增了其他引用jar,則必須重新啟動hadoop的相關進程。

    我們可以在hadoop-env.sh中,增加如下配置:

export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/path/customer/jars

    其中“/path/customer/jars”路徑為自己的第三方jar所在的本地路徑,我們需要在集群中所有的hadoop機器上都同步這些jar。

    瘦jar的打包方式(maven):

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>prepare-package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.app.script.Main</mainClass> </manifest> </archive> </configuration> </plugin>

    使用了copy-dependencies插件,當使用“mvn package”命令打包之后,第三方引用包會被copy到打包目錄下的lib文件中(並非mapreduce-job jar內部的lib文件中),開發者只需要把這些jars上傳到所有hadoop集群即可。

2. mapred.child.env

    我們可以指定mapreduce的task子進程啟動時加載第三方jars,而不是讓所有的hadoop子進程都加載。通過在mapred-site.xml中增加如下配置:

<property> <name>mapred.child.env</name> <value>LD_LIBRARY_PATH=/path/customer/jars</value> <!-- LD_LIBRARY_PATH=$HADOOP_HOME/mapred-lib/thirdparty --> </property>

    這種方式和1)類似,不過更加便捷,每個mapper或者reducer子進程啟動時都會重新加載第三方jars,所以當jars有變動時,只需要直接覆蓋它們即可,而無需重啟hadoop或者yarn。

3. -libjars選項

    我們可以在使用“hadoo jar”命令時,向啟動的job傳遞“libjars”選項參數,同時配合ToolRunner工具來解析參數並運行Job,這種方式是推薦的用法之一,因為它可以簡單的實現job的依賴包和hadoop classpath解耦,可以為每個job單獨設置libjars參數。這些jars將會在job提交之后復制到hadoop“共享文件系統中”(hdfs,/tmp文件夾中),此后taskTracker即可load到本地並在任務子進程中加載。

    libjars中需要指定job依賴的所有的jar全路徑,並且這些jars必須在當前本地文件系統中(並非集群中都需要有此jars),暫時還不支持hdfs。對於在HADOOP_CLASSPATH或者mapred.child.env中已經包含了jars,則不需要再-libjars參數中再次指定。因為libjars需要指定jar的全路徑名,所以如果jars特別多的話,操作起來非常不便,所以我們通常將多個job共用的jars通過HADOOP_CLASSPATH或者mapred.child.end方式配置,將某個job依賴的額外的jars(少量的)通過-libjars選項指定。

hadoop jar statistic-mr.jar com.statistic.script.Main -libjars /path/cascading-core-2.5.jar,/path/cascading-hadoop-2.5.jar

4. Fatjar

    胖jar,即將mapreduce-job jar所依賴的所有jar都“shade”到一個jar中,最終package成一個“獨立”的可運行的jar;當然hadoop並不需要這個jar是“可運行的”,它只需要這個jar在運行時不需要額外的配置“--classpath”即可。此外Fatjar仍然可以使用HADOOP_CLASSPATH或者map.child.env所加載的jars,因為我們在打包時可以將這些jars排除,以減少fatjar的大小。

    fatjar只不過是一種打包的方式,也仍然可以和“-libjars”選項配合。不過從直觀上來說,fatjar確實是解決“-libjars”不方便的技巧。

    此例中,我們使用cascading來開發一個mapreduce job,但是我們又不希望cascading的相關依賴包被放入HADOOP_CLASSPATH中,因為其他的job可能不需要或者其他的job有可能使用其他版本的cascading;所以就使用Fatjar,把job程序和cascading的依賴包全部“shade”在一起。

    使用maven assambly插件來完成fatjar的打包工作:

    1) pom.xml

<build> <finalName>statistic-mapred</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptors> <descriptor>src/assembly.xml</descriptor> </descriptors> <archive> <!-- optional --> <!-- <manifest> <mainClass>com.script.Main</mainClass> <addClasspath>true</addClasspath> </manifest> --> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>

    2) assambly.xml

<assembly> <id>cascading</id> <formats> <format>jar</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <unpack>true</unpack> <scope>runtime</scope> <!-- <excludes> <exclude>org.apache.hadoop:*</exclude> </excludes> --> <!-- very small jar --> <includes> <include>cascading:*</include> <include>thirdparty:*</include> </includes> </dependencySet> </dependencySets> <fileSets> <fileSet> <directory>${project.build.outputDirectory}</directory> <outputDirectory>/</outputDirectory> </fileSet> </fileSets> </assembly>

   在assambly.xml中我們通過<include>標簽來包含需要被“shade”的第三方依賴包,並且采用了unpack(解壓)方式,此例中我們只將cascading的jar打進fatjar中,對於其他包將會被忽略,因為這些包已經在hadoop中存在(比如hadoop,hdfs,mapreduce,已經其他的常用包,都可以共用hadoop的),最終我們的打包結果如下:



 

    有了fatjar,確實大大的減少了開發工程師部署mapreduce的復雜度和出錯的可能性,如果你有即備的maven環境,建議使用fatjar的方式。將fatjar直接放在hadoop中使用“hadoop jar”指令即可執行,幾乎無需關心依賴包遺漏的問題。

    此外,需要備注一下,在使用cascading時,如果采用了HADOOP_CLASSPATH或者mapred.child.env方式管理依賴時,會偶爾拋出:

Split class cascading.tap.hadoop.MultiInputSplit not found

    盡管cascading的所有依賴包都在CLASSPATH中,也無法解決這個問題,不確定究竟發生了什么!!后來采用了fatjar之后,問題解決!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM