阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Hadoop作业引用第三方jar文件

191次阅读
没有评论

共计 2608 个字符,预计需要花费 7 分钟才能阅读完成。

在 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 作业提交分析 http://www.linuxidc.com/Linux/2012-04/59199.htm >.

有 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 提交过程, 如下图所示.

Hadoop 作业引用第三方 jar 文件

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 过程解析> http://www.linuxidc.com/Linux/2011-11/47052.htm).

 

三. 总结

要想让 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 一个对象.

Hadoop 怎样提交多个第三方 jar 包?http://www.linuxidc.com/Linux/2012-02/53759.htm

更多 Hadoop 相关信息见Hadoop 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=13

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计2608字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中