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

【转】Mapreduce部署与第三方依赖包管理的更多相关文章

  1. Mapreduce部署与第三方依赖包管理

    Mapreduce部署是总会涉及到第三方包依赖问题,这些第三方包配置的方式不同,会对mapreduce的部署便捷性有一些影响,有时候还会导致脚本出错.本文介绍几种常用的配置方式: 1. HADOOP_ ...

  2. flutter如何使用配置文件pubspec.yaml(位于项目根目录)来管理第三方依赖包

    官方文档 在软件开发中,很多时候有一些公共的库或SDK可能会被很多项目用到,因此,将这些代码单独抽到一个独立模块,然后哪个项目需要使用时再直接集成这个模块,便可大大提高开发效率.很多编程语言或开发工具 ...

  3. Java基础-Eclipse第三方安装包管理工具之Maven

    Java基础-Eclipse第三方安装包管理工具之Maven 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 玩过Linux的小伙伴应该都知道yum吧,我们只要把搭建好的yum仓库配 ...

  4. go依赖包管理工具vendor基础

    go依赖包管理工具vendor基础 vendor是go的依赖包管理工具,主要用于管理项目中使用到的一些依赖. 它将项目依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的 ...

  5. bower一个强大的前端依赖包管理工具

    在介绍之前,你必须的知道bower是基于nodejs开发的,所以你首先必须得有个nodejs环境,至于这么安装nodejs网上一大堆教程,对了使用bower还需要安装git,这里就不多说了. #### ...

  6. Maven 手动添加第三方依赖包及编译打包和java命令行编译JAVA文件并使用jar命令打包

    一,实例:新建了一个Maven项目,在eclipse中通过 build path –> configure path-.将依赖包添加到工程中后,eclipse不报错了.但是用Maven命令 mv ...

  7. 安装CDH第三方依赖包

    安装CDH第三方依赖包: yum install chkconfig python bind-utils psmisc libxslt zlib sqlite cyrus-sasl-plain cyr ...

  8. SAE 安装未包含的第三方依赖包

    如何使用virtualenv管理依赖关系 当你的应用依赖很多第三方包时,可以使用virtualenv来管理并导出这些依赖包,流程如下: 首先,创建一个全新的Python虚拟环境目录ENV,启动虚拟环境 ...

  9. eclipse打jar包解决第三方依赖包

    在项目根目录下手动MANIFEST.MF(eclipse无法自动生成) MANIFEST.MF Manifest-Version: 1.0 Class-Path: lib/kafka-clients- ...

随机推荐

  1. LeetCode Weekly Contest 47

    闲着无聊参加了这个比赛,我刚加入战场的时候时间已经过了三分多钟,这个时候已经有20多个大佬做出了4分题,我一脸懵逼地打开第一道题 665. Non-decreasing Array My Submis ...

  2. Nginx学习之HTTP/2.0配置

    哎呀,一不小心自己的博客也是HTTP/2.0了,前段时间对网站进行了https迁移并上了CDN,最终的结果是这酱紫的(重点小绿锁,安全标示以及HTTP/2.0请求). 科普 随着互联网的快速发展,HT ...

  3. SQL分组查询

      把数据分成多个逻辑组,以便能对每个组的数据进行操作,对每个组进行聚集计算. 1.创建分组 分组是在SELECT语句的GROUP BY子句中建立的 例子:         SELECT vendId ...

  4. python专题-函数式编程

    函数式编程是使用一系列函数去解决问题,按照一般编程思维,面对问题时我们的思考方式是"怎么干",而函数函数式编程的思考方式是我要"干什么". 至于函数式编程的特点 ...

  5. httpd2.4常用配置

    author:JevonWei 版权声明:原创作品 httpd 2.4配置 切换使用的MPM Centos7:/etc/httpd/conf.modules.d/00-mpm.conf 启用要启用的M ...

  6. 主从及转发DNS搭建

    author:JevonWei 版权声明:原创作品 主DNS 安装bind软件包 yum -y install bind systemctl start named systemctl enable ...

  7. 《个人-GIT使用方法》

    使用GIT版本控制工具及基本使用方法(安装,新建,推送,拉取),托管平台的使用方法. Git 常用命令 git init here -- 创建本地仓库(repository),将会在文件夹下创建一个 ...

  8. 深度剖析Redis持久化

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt118 Redis是一种面向"key-value"类型数据 ...

  9. java 多线程(0) Java线程

    线程 线程是系统调度的基本单元,每当创建一个进程时,会有许多的线程,也叫轻量级进程,在一个进程中拥有多个线程,各自都有自己的计数器,堆和局部变量属性,并且能够分享内存变量. 为什么要使用多线程  1. ...

  10. JavaScript 的使用基础总结①

    JavaScript 使用   JavaScript 是一种轻量级的编程语言,JavaScript 是可插入 HTML 页面的编程代码,JavaScript 插入 HTML 页面后,可由所有的现代浏览 ...