Eclipse中运行Hadoop程序的各种问题

作者: yuanyaxin
发布时间:2015-07-21 10:11:37

     搭建了一个Hadoop集群(一个master,三个slave),参照Hadoop实战上的wordcount代码,在eclipse运行,但是在web页面上查不到该job的id,后来发现是在单机上运行,那搭建这个集群还有什么意义,于是在网上查找答案,试着在eclipse中将hadoop程序在集群中跑起来。却发现其中问题不少啊。

     1.如何使eclipse中的hadoop程序在集群而不是单机上运行

      通过源码,首先是创建一个configuration对象,并且对参数进行解析,接着提交作业所用的Job对象,设置作业jar包,对应的Mapper类和Reducer类,输入输出的Key和Value的类及作业的输入和输出路径,最后就是提交作业并等待作业结束。

   

String tracker = conf.get("mapred.job.tracker", "local");
    if ("local".equals(tracker)) {
      this.jobSubmitClient = new LocalJobRunner(conf);
    } else {
      this.jobSubmitClient = createRPCProxy(JobTracker.getAddress(conf), conf);
    }  


发现原来跟conf文件夹中mapred-site.xml中mapred.job.tracker的属性是否设置有关,在eclipse之前都没将配置文件添加进来,怪不得在Local运行,后来想想也是,你的配置文件都没添加进来,都找不到JobTracker和TaskTracker的位置,怎么可能在集群运行呢······解决这个问题很简单,只需要将hadoop中已经配置好的conf文件夹考到当前工程,并添加到工程的build path中,这样就能在集群上运行了!(这同时也解释了在命令行为什么就不是在单机上运行了,因为conf中的配置文件是已经添加到路径中去了的)

具体可以参考博客http://www.cnblogs.com/spork/archive/2010/04/21/1717552.html 这位老兄讲得很详细。

 

  2.Map函数无法找到

做完第一步后,以为可以运行了,却发现提示java.lang.RuntimeException: java.lang.ClassNotFoundException: Job$Mapper. 

看了下编译后的文件,发现Map和Reduce内部类已经编译好了啊,为什么会找不到啊,果断把提示的错误复制,百度,发现是Job.setJarByClass(xxx.class)设置jar没有成功,将网上答案抄了下来

在eclipse运行,使用了WordCount.class的类加载器来寻找包含该类的Jar包,然后设置该Jar包为作业所用的Jar包。但是我们的作业 Jar包是在程序运行时才打包的,而WordCount.class的类加载器是AppClassLoader,运行后我们无法改变它的搜索路径,所以使用setJarByClass是无法设置作业Jar包的。我们必须使用JobConf里的setJar来直接设置作业Jar包。就是添加下面这一句

                                                       ((JobConf)job.getConfiguration()).setJar(jarFile);

其中的jarFile是你已经打包好了的,输入该jar包的路径就OK(在命令行中完全省略这一步,直接job.setJarByClass就好了)

参考博客http://www.cnblogs.com/spork/archive/2010/04/21/1717592.html

 

3.如何打包

上文提到,需要自己打包,当你的代码中没有用到第三方的jar包的时候,这时是相当轻松的,使用eclipse的export,无论打成普通的jar包还是runnable jar都是没有问题的。但是当时我的应用中是用到了第三方的jar包的,由于hadoop需要将该jar包分发到tasktracker运行,而tasktracker主机肯定是没有下载第三方jar包的。于是我想到了打成一个runnable jar,里面包含我所需要的第三方jar包。我使用该jar包中的类是在Map函数中,Map函数肯定是在Tasktracker运行,但是运行时提示始终找不到该类,我明明是加进去了的啊,我猜想是不是打包格式不对啊,烦!百度之,找关于hadoop如何分发本机jar包,果不其然,两种解决方案

1.将第三方的jar包所有的class与我们自己代码打包在一起。这其实很容易做到,使用eclipse的export功能打包成runnable jar,然后选第一项就可以了。

2.创建一个lib目录,把所依赖的jar包放到该目录,再和代码一起打包。

参考博客http://blog.iamzsx.me/show.html?id=185002

 

4.在命令行如何运行有层次的jar包

比如我的主类是Wordcount,但是该类是在包word下,那么运行在eclipse底下是没任何问题的,但是当打包以后,却发现不能运行。网上找答案,发现无一例外都是要运行下面的命令Hadoop jar xxx.jar word.Wordcount input output 

但是还是不行,最后发现当打包runnable的第一种方式,即第三方的jar包所有的class与我们自己代码打包在一起,并设置好主类就可以了(在MAINFEST中进行设置)。 这时候的命令为 Hadoop jar xxx.jar input output(不需要设置主函数,因为在打包时候已经设置好了)

 

总结下,上面几个看似很简单的问题花费了我几天时间,但想想问题出现在:

1.对打包方式不熟悉

2.没有深刻理解hadoop的内部机制

才会出现上述问题

 另外,分享打包语句

 jar cvfm xxx.jar manifest -C 文件夹/ .  -m 是用自己的mainfest(Main-Class)

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

标签: Eclipse Hadoop
来源:http://blog.csdn.net/yuanyaxin/article/details/18229933

推荐: