问题描述
写MR程序往往需要依赖第三方依赖库,或者需要读取自己的配置文件,
本文就的目的就是为了用靠谱的方法解决这两个问题!
解决方案
步骤
- 在 Driver 端添加依赖
export HADOOP_CLASSPATH="thirdpartlib_1.jar,thirdpartlib_2.jar ..."
- 在 Task 端添加依赖(或配置文件)
hadoop jar application.jar \
-libjars "thirdpartlib_1.jar,thirdpartlib_2.jar ..." \
-files "file1, file2 ..." \
userparam1, userparam2 ...
注意1: 必须保证 "-libjars" 和 "-files" 在 "hadoop jar application.jar" 后面 并且在 "userparam1, userparam2 ..." 前面!如果在 "userparam1, userparam2 ..." 后面,则会被当做 userparam 处理。
注意2: 此种方法会把配置文件放到application.jar的同级目录
- 代码
Configuration conf = new Configuration();
String[] userparams = new GenericOptionsParser(conf, args).getRemainingArgs();
Job job = Job.getInstance(conf);
//process business logic ...
System.exit(job.waitForCompletion(true) ? 0 : 1)
public class ApplicationDriver extends Configured implements Tool {
//设定并读取应用程序相关的,自己定义的一些参数
public int run(String[] args) throws Exception {
if(args.length < 2) {
printUsage();
return 2;
}
Job job = new Job(getConf());
//process business logic ...
return job.waitForCompletion(true) ? 0 : 1;
}
//真正的main函数
public static void main(String[] args) throws Exception{
int res = ToolRunner.run(new Configuration(), new ApplicationDriver(), args);
System.exit(res);
}
}
注意:必须使用 "方法1" 或者 "方法2" 才能使 "1" 和 "2" 生效!
原理
-files:Hadoop 将指定的本地/hdfs上的文件通过HDFS分发到各个Task的工作目录下,不对文件进行任何处理
-libjars:Hadoop 将指定的本地/hdfs上的jar包通过HDFS分发到各个Task的工作目录下,并将其自动添加到任务的CLASSPATH环境变量中
原理是基于 Hadoop 的 DistributedCache,详解见如下链接: http://dongxicheng.org/mapreduce-nextgen/hadoop-distributedcache-details/
常见问题
- 增加了 "export HADOOP_CLASSPATH" 环境变量, Driver 端仍然找不到类
原因a: 在 "hadoop jar application.jar ..." 后面用了 sudo,导致环境变量不能传递给子进程
解决:"sudo" 替换为 "sodu -E",使父进程的环境变量不被抹除
- 增加了 -libjars 操作, 但是 Task 端仍然找不到类
原因a: 没有使用 "步骤3" 的两种方法使 "-libjars" 生效
解决: 使用 "步骤3" 中的两种方法的任意一个
原因b: "-libjars" 放在了 "userparam1, userparam2 ..." 的后面
解决: 将 "-libjars" 在 "hadoop jar application.jar" 后面 并且在 "userparam1, userparam2 ..." 前面!
网友评论