hadoop运行第三方jar

在eclipse中写mapreduce程序, 引用第三方jar文件, 可以利用eclipse hadoop插件直接run on hadoop提交, 很方便.  不过插件版本要和eclipse匹配, 不然总是local执行, 在50070是没有job产生的.

如果希望将程序发布成jar文件, 在namenode上通过命令行方式执行, 缺少了eclipse帮忙自动配置jar文件, 会遇到java.lang.ClassNotFoundException, 这个问题可分成两种情况讨论.

一. hadoop命令式如何执行的?

其实$HADOOP_HOME/bin/hadoop是一个脚本文件.  以下wordcount命令为例

bin/hadoop jar wordcount.jar myorg.WordCount /usr/wordcount/input /usr/wordcount/output

脚本文件解析参数, 配置类路径等, 最终执行的是如下命令:

exec java -classpath $CLASSPATH org.apache.hadoop.util.RunJar $@

其中$CLASSPATH : 包含${HADOOP_CONF_DIR}, $HADOOP_HOME下的*.jar以及$HADOOP_CLASSPATH;

  • $@ :  所有脚本参数, 此处为jar后面的参数; 
  • RunJar : 这个类的功能比较简单, 将jar文件解压到“hadoop.tmp.dir”目录下, 然后执行我们指定的类, 此处即为myorg.WordCount

p.s. hadoop脚本比较完整的分析可参见<Hadoop作业提交分析>.

有RunJar执行WordCount后, 就进入我们的程序了, 需要配置mapper, reducer以及输出输出路径等等, 最终通过执行job.waitForCompletion(true)向JobTracker提交这个作业.

到目前可知, 已经完成了本地执行部分, 如果这段时期发生ClassNotFoundException, 则可以在自己的脚本文件中配置$HADOOP_CLASSPATH, 包含需要的第三方jar文件, 再执行hadoop命令, 此为情况一.

 

二. JobTracker和TaskTracker如何获得第三方jar文件?

有时候提交job之后, 在map或者reduce函数中也会产生ClassNotFoundException. 这是因为map或reduce可能在其他机器上执行, 那些机器没有需要的jar文件, mapreduce作业交由JobTracker和TaskTracker执行, 两者如何获得第三方jar文件呢?  即为情况二.

我们首先来分析下mapreduce提交过程, 如下图所示.

mapreduce job提交过程

step 1.和2. 通过Job类提交作业,  获得一个作业号, 并根据conf决定作业时提交给LocalJobRunner还是JobTracker

step 3.  copy job resource

client将作业所需资源上传到hdfs上, 如job split, jar文件等.  JobClient通过configureCommandLineOptions函数处理jar文件, 该方法中通过job获得这些参数内容

files = job.get("tmpfiles"); // 对应参数项-files
libjars = job.get("tmpjars"); // 对应-libjars
archives = job.get("tmparchives"); // 对应-archives

如果jar文件有配置, 则将其加入到分布式缓存DistributedCache中, -libjars为例:

if (libjars != null) {
    FileSystem.mkdirs(fs, libjarsDir, mapredSysPerms);
    String[] libjarsArr = libjars.split(",");
    for (String tmpjars: libjarsArr) {
        Path tmp = new Path(tmpjars);
        Path newPath = copyRemoteFiles(fs, libjarsDir, tmp, job, replication);
        DistributedCache.addArchiveToClassPath(newPath, job);
    }
}

另外, 在mapreduce程序的配置中总是需要job.setJarByClass来指定运行的类,  如此hadoop就可以根据该class定位到所在的jar文件, 就是我们打包的jar, 将其上传到hdfs上. 到此jobClient完成了资源复制过程, 这些资源可供JobTracker和TaskTracker使用.

step4-10.   JobClient提交job并执行作业(JobTracker以及TaskTracker工作就不展开了, 详见<Map-Reduce过程解析>).

 

三.  总结

要想让mapreduce程序引用第三方jar文件, 可以采用如下方式:
  1. 通过命令行参数传递jar文件, 如-libjars等;
  2. 直接在conf中设置, 如conf.set(“tmpjars”,*.jar), jar文件用逗号隔开;
  3. 利用分布式缓存, 如DistributedCache.addArchiveToClassPath(path, job), 此处的path必须是hdfs, 即自己讲jar上传到hdfs上, 然后将路径加入到分布式缓存中;
  4. 第三方jar文件和自己的程序打包到一个jar文件中, 程序通过job.getJar()将获得整个文件并将其传至hdfs上. (很笨重)
  5. 在每台机器的$HADOOP_HOME/lib目录中加入jar文件. (不推荐)

p.s. 如果通过上面方法1.或2., 需要注意Configuration问题, 需要通过getConf()函数获得, 而不要自己new一个对象.

6 .在你的project里面建立一个lib文件夹,然后把所有的第三方jar包放到里面去,Hadoop会自动加载lib依赖里面的jar

<?xml version="1.0" encoding="UTF-8"?>

<project name="stat" default="job">
<property name="name" value="${Project.name}" />
<property name="version" value="0.1" />
<property name="build" value="build" />
<property name="build.classes" value="${build}/classes" />
<property name="build.unjar" value="${build}/unjar" />
<property name="dist" value="dist" />
<property name="src" value="src" />
<property name="lib" value="lib" />
<property name="conf" value="conf" />

<path id="project.class.path">
<fileset dir="${lib}">
<include name="*.jar" />
</fileset>
</path>


<target name="init">
<delete dir="${build}" />
<delete dir="${dist}" />
<mkdir dir="${build}" />
<mkdir dir="${build.classes}" />
<mkdir dir="${dist}" />
</target>


<target name="compile" depends="init">
<javac debug="true" srcdir="${src}" destdir="${build.classes}" includeantruntime="true">
<classpath refid="project.class.path" />
</javac>
</target>
<target name="job" depends="compile">
<jar jarfile="${dist}/${name}.jar">
<manifest>
<attribute name="Classpath" value="*.jar;*.properties;"/>
</manifest>
<zipfileset dir="${build.classes}"/>
<zipfileset dir="${lib}" prefix="lib" includes="**/*.*" excludes="hadoop-*.jar">
</zipfileset>
</jar>
</target>
<target name="clean">
<delete dir="${build}" />
<delete dir="${dist}" />
</target>
</project>

切记 第三方的jar代码里面不能调用另外第三方jar


的类文件否则会发生找不到另外第三方jar的类的


错误(原因不明),需要将调另外第三方jar的


类的类文件改为自己项目的类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Hadoop中使用第三方MapReduce程序,需要将程序打包成一个可执行的jar文件,并将其上传到Hadoop集群上。这个jar文件需要上传到所有的Hadoop节点上,包括NameNode和DataNode节点。这样才能确保程序在整个Hadoop集群中都可以运行。一般情况下,可以使用Hadoop自带的hadoop命令行工具来上传jar文件到Hadoop集群中。具体操作步骤可以参考Hadoop官方文档。 ### 回答2: Hadoop使用第三方的MapReduce,需要上传到集群中的所有节点上。 Hadoop是一个分布式计算框架,其核心思想是将大规模数据集分解为多个小数据块,并将这些数据块分散存储在不同的节点上。当使用第三方的MapReduce时,Map任务和Reduce任务需要执行在集群中的不同节点上,以实现并行计算和分布式处理。 在Hadoop中,我们通常会将自己编写的MapReduce程序打包成一个JAR文件,并使用Hadoop提供的命令将该JAR文件上传至Hadoop集群。一旦成功上传到集群上,Hadoop会将该JAR文件在各个节点上进行复制和分发,以确保所有节点上都能够访问到该文件。 当我们通过Hadoop提交任务时,Hadoop会按照设定的配置,在集群中选择一定数量的节点作为任务执行节点。对于Map任务,每个任务节点将会接收到一部分输入数据进行处理;而对于Reduce任务,不同的任务节点将接收到不同的Map任务输出结果,进行进一步的处理。 因此,当使用第三方的MapReduce时,其执行过程需要上传到集群中的所有节点上,以保证任务能够在集群中的各个节点上进行并行计算,从而实现更高效的大规模数据处理。 ### 回答3: Hadoop 使用第三方 MapReduce 时,需要将程序上传到集群中的几个节点上。 在 Hadoop 集群中,通常由一个 Master 节点和多个 Slave 节点组成,Master 节点负责调度任务和管理整个集群的状态,而 Slave 节点则负责执行任务。 当我们利用 Hadoop 运行第三方 MapReduce 程序时,需要将该程序上传到集群中的两个节点上,分别是 Master 节点和一个 Slave 节点。在 Master 节点上,我们需要上传该程序的驱动代码,用于调度和管理 MapReduce 任务的执行。同时,在一个 Slave 节点上,我们需要将 MapReduce 程序的其他相关文件(如 Mapper 和 Reducer)上传,用于实际的数据处理和计算。 上传这些文件到集群节点上,可以通过 Hadoop 提供的命令行工具或者通过 Hadoop 的 Web 界面进行操作。具体的步骤如下: 1. 将 MapReduce 程序的驱动代码上传到 Master 节点。 - 可以通过命令行使用 `hadoop fs` 命令将代码文件上传到 Hadoop 分布式文件系统(HDFS)中。 - 或者通过 Web 界面使用 Hadoop 的文件浏览器将代码文件上传到 HDFS 中。 2. 将 MapReduce 程序的其他相关文件上传到一个 Slave 节点上。 - 同样可以通过命令行使用 `hadoop fs` 命令将文件上传到 HDFS 中。 - 或者通过 Web 界面使用 Hadoop 的文件浏览器将文件上传到 HDFS 中。 上传完成后,Hadoop 将自动将这些文件分发到集群中的对应节点上,以供 MapReduce 任务的执行。 需要注意的是,具体需要上传到几个节点上,取决于集群的配置和并发任务的需求。在一个典型的 Hadoop 集群中,通常会有多个 Slave 节点,我们可以选择将程序上传到其中的一个节点上,然后 Hadoop 会自动将其分发到其他 Slave 节点上,并同时运行多个实例以处理不同的数据块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值