如何从 Eclipse 调试 hadoop mapreduce 作业?

Posted

技术标签:

【中文标题】如何从 Eclipse 调试 hadoop mapreduce 作业?【英文标题】:How to debug hadoop mapreduce jobs from eclipse? 【发布时间】:2012-04-12 12:50:29 【问题描述】:

我在单机、仅限本地的设置中运行 hadoop,我正在寻找一种在 eclipse 中调试映射器和缩减器的好方法。 Eclipse 运行 mapreduce 任务没有问题。但是,当我去调试时,它给了我这个错误:

12/03/28 14:03:23 WARN mapred.JobClient:未设置作业 jar 文件。可能找不到用户类。请参阅 JobConf(Class) 或 JobConf#setJar(String)。

好的,所以我做一些研究。显然,我应该使用 eclipse 的远程调试工具,并将其添加到我的hadoop-env.sh

-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5000

我这样做了,我可以在 Eclipse 中单步执行我的代码。唯一的问题是,由于“suspend=y”,我不能使用命令行中的“hadoop”命令来执行诸如查看作业队列之类的操作;它挂起,我在想象,因为它正在等待调试器附加。另外,当我处于这种模式时,我无法运行“hbase shell”,可能是出于同样的原因。

所以基本上,如果我想在“调试模式”和“正常模式”之间来回切换,我需要更新hadoop-env.sh 并重新启动我的机器。大痛。所以我有几个问题:

    有没有更简单的方法在 eclipse 中调试 mapreduce 作业?

    为什么 eclipse 可以很好地运行我的 mapreduce 作业,但要进行调试,我需要使用远程调试?

    有没有办法告诉 hadoop 对 mapreduce 作业使用远程调试,但对所有其他任务在正常模式下运行? (例如“hadoop queue”“hbase shell”)。

    有没有更简单的方法来切换hadoop-env.sh 配置而无需重新启动我的机器? hadoop-env.sh 默认是不可执行的。

    这是一个更普遍的问题:当我在本地模式下运行 hadoop 时到底发生了什么?我的机器上是否有任何进程“始终开启”并执行 hadoop 作业?或者当我从命令行运行“hadoop”命令时,hadoop 是否只做一些事情?当我从 eclipse 运行 mapreduce 作业时,eclipse 在做什么?我必须在我的pom.xml 中引用hadoop-core 才能使我的项目正常工作。 eclipse 是向我安装的 hadoop 实例提交作业,还是以某种方式从我的 maven 缓存中的 hadoop-core-1.0.0.jar 运行它?

这是我的主要课程:

public class Main 
      public static void main(String[] args) throws Exception      
        Job job = new Job();
        job.setJarByClass(Main.class);
        job.setJobName("FirstStage");

        FileInputFormat.addInputPath(job, new Path("/home/sangfroid/project/in"));
        FileOutputFormat.setOutputPath(job, new Path("/home/sangfroid/project/out"));

        job.setMapperClass(FirstStageMapper.class);
        job.setReducerClass(FirstStageReducer.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);

        System.exit(job.waitForCompletion(true) ? 0 : 1);
      

【问题讨论】:

顺便说一句,如果你只是想调试你的映射器/减速器逻辑,你应该考虑使用 MRUnit (cloudera.com/blog/2009/07/…) @Chris White 建议从 MRUnit 开始测试 Map/Reduce 逻辑是个好主意:incubator.apache.org/projects/mrunit.html 【参考方案1】:

除了推荐的 MRUnit 之外,我还喜欢使用 eclipse 进行调试。我有一个主程序。它实例化一个配置并直接执行 MapReduce 作业。我只是使用标准的 Eclipse 调试配置进行调试。因为我在我的 mvn 规范中包含了 hadoop jar,所以我的类路径中包含所有 hadoop 本身,我不需要针对我安装的 hadoop 运行它。我总是在本地目录中使用小型数据集进行测试,以使事情变得简单。配置的默认行为就像一个独立的 hadoop(文件系统可用)

【讨论】:

感谢您的回答。我也将 hadoop-core 设置为我的 POM 中的依赖项。既然是这种情况,为什么我会收到“没有设置作业 jar 文件”错误?是因为我在调用 job.setJarByClass() 吗?能否请您发布一些示例代码?【参考方案2】:

在 Eclipse 中调试 hadoop 的唯一方法是在本地模式下运行 hadoop。原因是,每个 map reduce 任务都在自己的 JVM 中运行,当您不在本地模式下使用 hadoop 时,eclipse 将无法调试。

当您将 hadoop 设置为本地模式时,而不是使用 hdfs API(这是默认设置),hadoop 文件系统将更改为 file:///。因此,运行hadoop fs -ls 将不是一个hdfs 命令,而是更多hadoop fs -ls file:///,一个本地目录的路径。 JobTracker 或 NameNode 均未运行。

这些博文可能会有所帮助:

http://let-them-c.blogspot.com/2011/07/running-hadoop-locally-on-eclipse.html http://let-them-c.blogspot.com/2011/07/configurations-of-running-hadoop.html

【讨论】:

嗨@Kapil,您所描述的内容在 Hadoop 2.4 中是可能的(使用 Yarn 等)。我正在尝试使用新版本在 Eclipse 中运行本地作业并面临Cannot initialize Cluster. Please check your configuration... @PedroDusso 你有本地调试来使用 Hadoop 2.4+ 吗? @erichfw 我从未尝试过...我在问这个问题时使用的是 2.2。【参考方案3】:

我还喜欢通过带有 MRUnit 的单元测试进行调试。我将把它与approvaltests 结合使用,它可以创建Map Reduce 过程的简单可视化,并且可以很容易地传递失败的场景。它还可以从 eclipse 无缝运行。

例如:

HadoopApprovals.verifyMapReduce(new WordCountMapper(), 
                         new WordCountReducer(), 0, "cat cat dog");

将产生输出:

[cat cat dog] 
-> maps via WordCountMapper to ->
(cat, 1) 
(cat, 1) 
(dog, 1)

-> reduces via WordCountReducer to ->
(cat, 2) 
(dog, 1)

这里有一个关于这个过程的视频:http://t.co/leExFVrf

【讨论】:

【参考方案4】:

/bin/hadoop (hadoop-env.sh) 脚本中进行更改。检查以查看已触发的命令。如果命令为jar,则只添加远程调试配置。

if [ "$COMMAND" = "jar" ] ; then
  exec "$JAVA" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8999 $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS "$@"
else
  exec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS "$@"
fi

【讨论】:

我并没有完全尝试过,但我用 jdb 替换了 $JAVA(我试图使用 jdb 进行调试)。 jdb 从未识别出我试图放置在我希望程序停止的位置的断点。我假设问题是我没有在本地模式下运行。我还没有尝试过,但我假设 Kapil D 的建议是我需要遵循的。 您也可以将调试选项添加到 shell 的 $HADOOP_OPTS 变量中,而不必修改 hadoop 脚本。 export HADOOP_OPTS="$HADOOP_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8999"【参考方案5】:

可以通过 HADOOP_OPTS 环境变量向 hadoop 的内部 java 命令添加 args:

export HADOOP_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=5005,suspend=y"

【讨论】:

【参考方案6】:

您可以通过-Dmapreduce.map.java.opts传递调试参数。 例如,您可以运行 HBase Import 并在调试模式下运行映射器:

yarn jar your/path/to/hbase-mapreduce-2.2.5.jar import
     -Dmapreduce.map.speculative=false 
     -Dmapreduce.reduce.speculative=false 
     -Dmapreduce.map.java.opts="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=5005,suspend=y" 
     my_table /path/in/hdfs

请注意,这必须放在一行中,没有新行。 其他 map-reduce 应用程序可以以相同的方式启动,诀窍是通过 -Dmapreduce.map.java.opts 传递调试指令。

在 Eclipse 或 IntelliJ 中,您必须创建一个调试远程连接

Host=127.0.0.1 (or even a remote IP address in case Hadoop runs elsewhere)
Port=5005

我设法以这种方式调试导入。此外,您可以将映射器的数量限制为 1,如 here 所述,但这对我来说不是必需的。

一旦启动 map-reduve 应用程序,切换到您的 IDE 并尝试启动您的调试设置,这将在开始时失败。重复此操作,直到调试器挂接到应用程序。不要忘记事先设置断点。

如果您不想只调试您的应用程序,还想调试周围的 HBase/Hadoop 框架,您可以下载它们 here 和 here(通过“切换分支/标签”菜单按钮选择您的版本)。

【讨论】:

以上是关于如何从 Eclipse 调试 hadoop mapreduce 作业?的主要内容,如果未能解决你的问题,请参考以下文章

如何在win7下的eclipse中调试Hadoop2.2.0的程序

如何在win7下的eclipse中调试Hadoop2.2.0的程序

本地eclipse远程操作 hbase

IDEA远程调试hadoop程序

搭建Hadoop2.5.2+Eclipse开发调试环境

eclipse远程调试Hadoop