1

我使用 Apache Hadoop 1.2.1 开发了一个 map-reduce 程序。我使用 Eclipse IDE 进行了初始开发,以模拟 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/ 指定主类在哪里)

./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
...

所以它出错了,因为它找不到映射器类。有“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 集群上工作。谢谢!

4

2 回答 2

0

经过一些额外的工作,我能够解决自己的问题。最终,它归结为我构建 jar 文件的方式,然后我试图在 hadoop 集群上执行该文件。

我没有使用 eclipse 来构建 JAR 文件,而是使用命令行中的 Maven 来构建 JAR 文件。在 pom.xml 文件中,您可以使用以下几行来指定主类:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>maxTemp.MaxTemperature</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

在我的例子中,maxTemp 是包,MaxTemperature 是包含我的主要方法的类。这将导致包含在 maven 为您构建的 JAR 中的清单文件添加以下行:

Main-Class: maxTemp.MaxTemperature

现在,当您使用 hadoop 执行 jar 文件时,您将不再需要指定 mainClass,因为您已经在 jar 的清单中这样做了。如果 JAR 清单中没有这一行,您将需要使用以下语法在集群上执行作业:

./hadoop jarFile [mainClass] args...

使用清单文件中的行,您可以按如下方式执行作业:

./hadoop jarFile args...

顺便说一句,我遇到了一些问题,因为我正在使用 jeigen java 库来做一些线性代数。我的集群无法找到我使用过的依赖项(jeigen.jar),并且引发了更多错误。如本网站所述,我最终构建了一个胖罐子:

http://hadoopi.wordpress.com/2014/06/05/hadoop-add-third-party-libraries-to-mapreduce-job/

通过对我的 pom.xml 文件进行一些添加,我能够生成一个 maxTemp-jar-with-dependencies,然后集群能够找到我所有的依赖项,因为它们包含在 jar 文件中。我希望这有助于在未来节省一些时间。其中一些依赖项在我的本地系统上,Maven 无法获取它们。我能够将 maven 指向它们并使用以下命令手动安装它们:

mvn install:install-file -DgroupId=jeigen -DartifactId=jeigen -Dversion=1 -Dpackaging=jar -Dfile=/path/to/the/location/of/Jeigen.jar

这是我的 pom.xml 文件,它生成两个 jar,一个包含依赖项,一个不包含依赖项:

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>maxTemp</groupId>
  <artifactId>maxTemp</artifactId>
  <version>0.0.1</version>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>

      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>

      <plugin>  
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>maxTemp.MaxTemperature</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>

      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
          <configuration>
            <archive>
              <manifest>
                <mainClass>maxTemp.MaxTemperature</mainClass>
              </manifest>
            </archive>
            <descriptorRefs>
              <descriptorRef>
                jar-with-dependencies
              </descriptorRef>
            </descriptorRefs>
          </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>
  <dependencies>

    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>1.2.1</version>
    </dependency>

    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-core</artifactId>
      <version>1.2.1</version>
    </dependency>

    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-tools</artifactId>
      <version>1.2.1</version>
    </dependency>

    <dependency>
      <groupId>jeigen</groupId>
      <artifactId>jeigen</artifactId>
      <version>1</version>
    </dependency>

    <dependency>
      <groupId>jna</groupId>
      <artifactId>jna</artifactId>
      <version>4.0.0</version>
    </dependency>

  </dependencies>
</project>
于 2014-11-16T19:41:03.560 回答
0

您的文件中是否有导入语句:

import imageFeatures.KLSHMapper;

您还需要在 CLASSPATH 环境变量中包含包含 imageFeatures.KLSMapper 的 jar 文件。这是你在这里得到的非常奇怪和外国的代码,所以也许我离题了......

于 2014-11-12T19:40:43.807 回答