我使用ApacheHadoop1.2.1开发了一个MapReduce程序。我使用EclipseIDE进行初始开发,以模拟hadoop分布式计算环境,所有输入和输出文件都来自本地文件系统。这个程序将在eclipse中执行,没有任何问题。然后,我使用eclipse创建一个jar文件,并尝试在我的hadoop计算机集群上运行此文件,并收到错误:
下面是设置和运行hadoop作业的代码:
String outputPath = "/output";
String hadoopInstructionsPath = args[0];
Job job = new Job();
job.setJarByClass(Main.class); //setJarByClass is here but not found apparently?!?
job.setJobName("KLSH");
FileInputFormat.addInputPath(job, new Path(hadoopInstructionsPath));
FileOutputFormat.setOutputPath(job,new Path(outputPath));
job.setMapperClass(KLSHMapper.class);
job.setReducerClass(KLSHReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
System.exit(job.waitForCompletion(true) ? 0:1);
boolean success = job.waitForCompletion(true);
return success ? 0 : 1;
然后,我使用eclipse创建一个jar,使用file->export->runnable jar file创建要在集群上运行的jar文件。
我用来运行作业的命令如下(klsh.jar是jar文件的名称,/hadoopinstruction是args[0]输入参数,imagefeature.main/指定main类的位置)
./hadoop jar ./KLSH.jar /hadoopInstructions imageFeatures.Main/
这将产生以下输出:
14/11/12 11:11:48 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
14/11/12 11:11:48 WARN mapred.JobClient: No job jar file set. User classes may not be found. See JobConf(Class) or JobConf#setJar(String).
14/11/12 11:11:48 INFO input.FileInputFormat: Total input paths to process : 1
14/11/12 11:11:48 INFO util.NativeCodeLoader: Loaded the native-hadoop library
14/11/12 11:11:48 WARN snappy.LoadSnappy: Snappy native library not loaded
14/11/12 11:11:49 INFO mapred.JobClient: Running job: job_201411051030_0022
14/11/12 11:11:50 INFO mapred.JobClient: map 0% reduce 0%
14/11/12 11:11:56 INFO mapred.JobClient: Task Id : attempt_201411051030_0022_m_000000_0, Status : FAILED
java.lang.RuntimeException: java.lang.ClassNotFoundException: imageFeatures.KLSHMapper
...
所以它出错了,因为它找不到mapper类。有“no job jar file set”警告,但我觉得我已经在第一段代码中指定了job.setjarbyclass,所以我不知道为什么会抛出这个错误。。。
我还知道klshmapper类在jar中,因为如果我运行以下命令:
jar tf KLSH.jar
我得到了相当多的输出,但这里有一部分输出:
...
imageFeatures/Main.class
imageFeatures/Feature.class
imageFeatures/FileLoader.class
imageFeatures/KLSHMapper.class
...
很明显klshmapper类就在里面。。。我尝试过修改hadoop类路径以包含klsh.jar路径,尝试过将klsh.jar复制到dfs并尝试使用该路径而不是本地文件系统上的路径,还尝试过使用-libjars说明符执行作业。不管我尝试了什么,hadoop似乎都找不到我的mapper类。有人能指出我做错了什么吗?我似乎无法从在eclipse中工作的代码跳到在实际的hadoop集群上工作。谢谢!
2条答案
按热度按时间nmpmafwu1#
您的文件中是否有import语句:
您还需要在classpath环境变量中包含包含imagefeatures.klsmapper的jar文件。这是非常奇怪的外国代码,你在这里,所以也许我的方式偏离了目标。。。
jecbmhm32#
经过一些额外的工作,我能够解决我自己的问题。最终,它归结为我构建jar文件的方式,然后我尝试在hadoop集群上执行这个jar文件。
我没有使用eclipse来构建jar文件,而是使用命令行中的maven来构建jar文件。在pom.xml文件中,可以使用以下内容指定主类:
在我的例子中,maxtemp是包,maxtemp是包含我的main方法的类。这将导致maven为您构建的jar中包含的清单文件中添加以下行:
现在,当您使用hadoop执行jar文件时,您将不再需要指定main类,因为您已经在jar的清单中这样做了。如果jar清单中没有这一行,则需要使用以下语法在集群上执行作业:
使用清单文件中的行,您可以按如下方式执行作业:
作为旁白,我遇到了一些问题,因为我使用jeigenjava库来做一些线性代数。我的集群找不到我使用过的依赖项(jeigen.jar),它抛出了更多的错误。我最终建造了一个胖jar,正如在这个网站上所描述的:
http://hadoopi.wordpress.com/2014/06/05/hadoop-add-third-party-libraries-to-mapreduce-job/
通过向pom.xml文件添加一些内容,我能够生成一个带有依赖项的maxtemp jar,然后集群能够找到我的所有依赖项,因为它们都包含在jar文件中。我希望这有助于节省一些人在未来的时间。其中一些依赖关系依赖于我的本地系统,而maven无法去获取它们。我可以使用以下命令将maven指向它们并手动安装它们:
下面是我的pom.xml文件,它生成两个jar,一个包含依赖项,另一个不包含依赖项: