hadoop jar mrjob.jar ru.package.Main -files hdfs://0.0.0.0:8020/MyCatalog/jars/metadata.csv -libjars hdfs://0.0.0.0:8020/MyCatalog/jars/opencsv.jar,hdfs://0.0.0.0:8020/MyCatalog/jars/gson.jar,hdfs://0.0.0.0:8020/MyCatalog/jars/my-utils.jar /MyCatalog/http_requests.seq-r-00000 /MyCatalog/output/result_file
我确实得到了这些警告:
12/10/26 18:35:50 WARN util.GenericOptionsParser: The libjars file hdfs://0.0.0.0:8020/MyCatalog/jars/opencsv.jar is not on the local filesystem. Ignoring.
12/10/26 18:35:50 WARN util.GenericOptionsParser: The libjars file hdfs://0.0.0.0:8020/MyCatalog/jars/gson.jar is not on the local filesystem. Ignoring.
12/10/26 18:35:50 WARN util.GenericOptionsParser: The libjars file hdfs://0.0.0.0:8020/MyCatalog/jars/my-utils.jar is not on the local filesystem. Ignoring.
然后:线程“main”中的异常java.lang.NoClassDefFoundError: 在Main类中我尝试从名为my-utils.jar
的jar实例化类我做错了什么?
UPD: 我正在检查 GenericOptionsParser 的源代码:
/**
* If libjars are set in the conf, parse the libjars.
* @param conf
* @return libjar urls
* @throws IOException
*/
public static URL[] getLibJars(Configuration conf) throws IOException {
String jars = conf.get("tmpjars");
if(jars==null) {
return null;
}
String[] files = jars.split(",");
List<URL> cp = new ArrayList<URL>();
for (String file : files) {
Path tmp = new Path(file);
if (tmp.getFileSystem(conf).equals(FileSystem.getLocal(conf))) {
cp.add(FileSystem.getLocal(conf).pathToFile(tmp).toURI().toURL());
} else {
LOG.warn("The libjars file " + tmp + " is not on the local " +
"filesystem. Ignoring.");
}
}
return cp.toArray(new URL[0]);
}
所以: 1.逗号之间没有空格 2.仍然没有得到它...我试图指向:本地文件系统,hdfs文件系统,结果是一样的。似乎没有添加类......
答案 0 :(得分:4)
问题解决了。正确的调用是:
hadoop jar my-job.jar ru.package.Main -files /home/cloudera/uploaded_jars/metadata.csv -libjars /home/cloudera/uploaded_jars/opencsv.jar,/home/cloudera/uploaded_jars/gson.jar,/home/cloudera/uploaded_jars/url-raiting-utils.jar /MyCatalog/http_requests.seq-r-00000 /MyCatalog/output/scoring_result
其中
/ MyCatalog
是hdfs路径,
/家庭/ Cloudera的/ uploaded_jars /
是本地fs路径 问题出在工作罐中。 以前我尝试使用只有三个类的简单jar 来运行作业:Mapper,Reducer,Main class 。 现在我确实提供了另一个由maven生成的(它生成了两个) 第二个作业jar包含所有依赖库。在里面。结构看起来像: MY-job.jar
- LIB
- aopalliance-1.0.jar asm-3.2.jar avro-1.5.4.jar ... commons-beanutils-1.7.0.jar commons-beanutils-core-1.8.0.jar .. 。zookeeper-3.4.3-cdh4.0.0.jar
lib文件夹中有76个罐子。
它有效,但我不明白为什么。
答案 1 :(得分:1)
仅仅因为它们在HDFS上,并不意味着它们位于您正在运行的作业的类路径中。
如果你真的只是想解决这个问题,我会用maven来构建一个“胖罐”,其中包含你在一个jar中的所有依赖项。您可以使用shade plugin。
执行此操作但是,看着你的命令,它看起来是错的。我认为使用-libjars,described here使用“job”命令可能会更好。我不确定您是否可以使用“hadoop jar”命令指定外部jar。
答案 2 :(得分:0)
原因是您的mrjob.jar确定了Hadoop客户端作业所需的jar。您可以提供一个胖罐子,也可以将所有罐子包含在HADOOP_CLASSPATH下。
另一方面,-libjars设置Map和Reduce任务所需的其他jar。