如何在hadoop作业中添加外部jar?

g1m*_*hai 5 java hadoop mapreduce noclassdeffounderror

我有一个Hadoop工作,其中映射程序必须使用外部jar。

我试图将此罐子传递给映射器的JVM

通过hadoop命令上的-libjars参数

hadoop jar mrrunner.jar DAGMRRunner -libjars <path_to_jar>/colt.jar
Run Code Online (Sandbox Code Playgroud)

通过job.addFileToClassPath

job.addFileToClassPath(new Path("<path_to_jar>/colt.jar"));
Run Code Online (Sandbox Code Playgroud)

在HADOOP_CLASSPATH上。

g1mihai@hydra:/home/g1mihai/$ echo $HADOOP_CLASSPATH
<path_to_jar>/colt.jar
Run Code Online (Sandbox Code Playgroud)

这些方法均无效。这是我得到的堆栈跟踪。它抱怨的缺少的类是colt.jar中的SparseDoubleMatrix1D。

让我知道是否应提供任何其他调试信息。谢谢。

15/02/14 16:47:51 INFO mapred.MapTask: Starting flush of map output
15/02/14 16:47:51 INFO mapred.LocalJobRunner: map task executor complete.
15/02/14 16:47:51 WARN mapred.LocalJobRunner: job_local368086771_0001
java.lang.Exception: java.lang.NoClassDefFoundError: Lcern/colt/matrix/impl/SparseDoubleMatrix1D;
        at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462)
        at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522)
Caused by: java.lang.NoClassDefFoundError: Lcern/colt/matrix/impl/SparseDoubleMatrix1D;
        at java.lang.Class.getDeclaredFields0(Native Method)
        at java.lang.Class.privateGetDeclaredFields(Class.java:2499)
        at java.lang.Class.getDeclaredField(Class.java:1951)
        at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1659)
        at java.io.ObjectStreamClass.access$700(ObjectStreamClass.java:72)
        at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:480)
        at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:468)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:468)
        at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:365)
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:602)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
        at BoostConnector.ConnectCalculateBoost(BoostConnector.java:39)
        at DAGMapReduceSearcher$Map.map(DAGMapReduceSearcher.java:46)
        at DAGMapReduceSearcher$Map.map(DAGMapReduceSearcher.java:22)
        at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:145)
        at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:784)
        at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
        at org.apache.hadoop.mapred.LocalJobRunner$Job$MapTaskRunnable.run(LocalJobRunner.java:243)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: cern.colt.matrix.impl.SparseDoubleMatrix1D
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 28 more
Run Code Online (Sandbox Code Playgroud)

Isa*_*110 5

我相信这个问题值得详细解答,我昨天被这个问题困扰,浪费了很多时间。我希望这个答案可以帮助碰巧遇到这个问题的每个人。有几个选项可以解决此问题:

  1. 在应用程序jar文件中包括外部jar(依赖项JAR)。您可以使用Eclipse轻松地做到这一点。此选项的缺点是,它将使您的应用程序jar膨胀,并且MapRed作业将花费更多时间来执行。每次依赖项版本更改时,您都必须重新编译应用程序等。最好不要采用这种方法。

  2. 使用“ Hadoop类路径”-在命令行上运行命令“ hadoop classpath”,然后找到一个合适的文件夹,然后将jar文件复制到该位置,然后hadoop将从那里获取依赖项。这不适用于CloudEra等,因为您可能没有读/写权限,无法将文件复制到hadoop classpath文件夹。

  3. 我使用的选项是使用Hadoop jar命令指定-LIBJARS。首先,请确保您编辑驱动程序类:

    public class myDriverClass extends Configured implements Tool {
    
      public static void main(String[] args) throws Exception {
         int res = ToolRunner.run(new Configuration(), new myDriverClass(), args);
         System.exit(res);
      }
    
      public int run(String[] args) throws Exception
      {
    
        // Configuration processed by ToolRunner 
        Configuration conf = getConf();
        Job job = new Job(conf, "My Job");
    
        ...
        ...
    
        return job.waitForCompletion(true) ? 0 : 1;
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

现在,编辑“ hadoop jar”命令,如下所示:

public class myDriverClass extends Configured implements Tool {

  public static void main(String[] args) throws Exception {
     int res = ToolRunner.run(new Configuration(), new myDriverClass(), args);
     System.exit(res);
  }

  public int run(String[] args) throws Exception
  {

    // Configuration processed by ToolRunner 
    Configuration conf = getConf();
    Job job = new Job(conf, "My Job");

    ...
    ...

    return job.waitForCompletion(true) ? 0 : 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在让我们了解一下发生了什么。基本上,我们通过实现TOOL接口来处理新的命令行参数。ToolRunner用于运行实现Tool接口的类。它与GenericOptionsParser结合使用,以解析通用的hadoop命令行参数并修改工具的配置。

在我们的Main()中,我们正在调用ToolRunner.run(new Configuration(), new myDriverClass(), args)- 在用给定的通用参数进行解析之后,它通过Tool.run(String [])运行给定的Tool 。它使用给定的配置,如果为null,则构建一个配置,然后使用conf的可能修改版本设置工具的配置。

现在在run方法中,当我们调用getConf()时,将获得Configuration的修改版本。因此,请确保您的代码中包含以下行。如果您实现了其他所有功能,但仍然使用Configuration conf = new Configuration(),则将无法进行任何操作。

Configuration conf = getConf();
Run Code Online (Sandbox Code Playgroud)


221*_*21B 0

Use distributed cache - you can have any executable files, or small reference files in the cache and use it in your MR job.

https://hadoop.apache.org/docs/r1.2.1/api/org/apache/hadoop/filecache/DistributedCache.html

There are two ways of running MR job, one with class name at run time else mention the main class at the time of exporting the jar.

hadoop jar jarname.jar DriverClassName Input-Location Output-Location
hadoop jar jarname.jar Input-Location Output-Location
Run Code Online (Sandbox Code Playgroud)