• 【转】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之后,问题解决!!

  • 相关阅读:
    个人作业-Alpha项目测试
    第三次作业
    第二次作业
    第一次作业
    JQuery(一)页面加载,写入文本,对象转换,隐藏显示,基本选择器,层级选择器,基本过滤选择器,表单选择器,class操作,属性操作
    JavaScript(二)
    轮辐广告、简单选项卡
    div层随着页面大小变化相对位置不变、按钮隐藏一半鼠标放上去就出来,不放上去就退回去
    markDown语法详解
    Mybatis中动态SQL语句
  • 原文地址:https://www.cnblogs.com/Dhouse/p/6595344.html
Copyright © 2020-2023  润新知