eclipse中运行Map/Reduce程序

纯转自 使用Eclipse搭建Hadoop编程环境

在eclipse中使用hadoop插件编程,在网上找了不少帖子,最终该贴解决了在eclipse中直接run on hadoop,而不用打jar,上传到hadoop主机,然后在hadoop jar xxx.jar。

在前人的基础上,进行总结学习,发现bug,修改bug。

系统平台:Ubuntu14.04TLS(64位)

Hadoop环境:Hadoop2.7.1

Eclipse:Neon.2 Release(4.6.2)

Eclipse插件:hadoop-eclipse-plugin-2.7.1.jar

一.编译环境搭建

 

1.在eclipse上安装Hadoop插件

把下载好的hadoop-eclipse-plugin-2.7.1.jar文件拷贝到eclipse安装目录中的plugins文件夹内。如下图:

2.继续配置hadoop编译环境(方便配置,确保已经开启了 Hadoop

启动 Eclipse 后就可以在左侧的Project Explorer中看到DFS Locations

 

3.插件的配置

第一步:选择 Window 菜单下的 Preference。

此时会弹出一个窗体,点击选择 Hadoop Map/Reduce 选项,选择 Hadoop 的安装目录(例如:/home/hadoop/hadoop)。

第二步:切换 Map/Reduce 开发视图

选择Window 菜单下选择 Open Perspective -> Other,弹出一个窗体,从中选择Map/Reduce 选项即可进行切换。

第三步:建立与 Hadoop 集群的连接

点击Eclipse软件右下角的Map/Reduce Locations 面板,在面板中单击右键,选择New Hadoop Location

在弹出来的General选项面板中,General 的设置要与 Hadoop 的配置一致。一般两个 Host值是一样的,如果是伪分布式,填写 localhost 即可,这里使用的是Hadoop伪分布,设置fs.defaultFShdfs://localhost:9000,则 DFS Master Port 改为 9000Map/Reduce(V2) Master Port 用默认的即可,Location Name 随意填写。

 

Advanced parameters 选项面板是对 Hadoop 参数进行配置,就是填写 Hadoop 的配置项(/home/hadoop/hadoop/etc/hadoop中的配置文件),如果配置了 hadoop.tmp.dir,就要进行相应的修改。但修改起来会比较繁琐,可以通过复制配置文件的方式解决。只要配置General 就行了,点击 finishMap/Reduce Location 就创建完成。

二.在 Eclipse 中操作 HDFS 中的文件

配置好后,点击左侧Project Explorer 中的 MapReduce Location 就能直接查看 HDFS 中的文件列表了(HDFS 中要有文件,如下图是 WordCount的输出结果),双击可以查看内容,右键点击可以上传、下载、删除 HDFS 中的文件

如果无法查看,可右键点击Location 尝试 Reconnect 或重启 EclipseHDFS 中的内容更新后Eclipse 不会同步刷新,需要右键点击 Project Explorer中的MapReduce Location,选择Refresh,(文件比较大的情况下eclipse可能死掉,重启eclipse就行)才能看到更新后的文件。

 

三.在 Eclipse 中创建 MapReduce 项目

 

点击 File 菜单,选择 New -> Project...:

 

选择Map/Reduce Project,点击Next

填写 Projectname WordCount 即可,点击Finish就创建好了项目。

然后在左侧的Project Explorer 可以看到刚才建立的项目。

接着右键点击刚创建的WordCount 项目,选择 New -> Class

需要填写两个地方:在Package 处填写 org.apache.hadoop.examples;在Name 处填写WordCount。(包名、类名可以随意起)

 

创建 Class 完成后,在 Projectsrc中可以看到 WordCount.java 这个文件。将如下 WordCount的代码拷贝到该文件中。

 

 

[java] view plain copy

  1. package org.apache.hadoop.examples;  
  2.    
  3. import java.io.IOException;  
  4. import java.util.Iterator;  
  5. import java.util.StringTokenizer;  
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.Text;  
  10. import org.apache.hadoop.mapreduce.Job;  
  11. import org.apache.hadoop.mapreduce.Mapper;  
  12. import org.apache.hadoop.mapreduce.Reducer;  
  13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  15. import org.apache.hadoop.util.GenericOptionsParser;  
  16.    
  17. public class WordCount {  
  18.     public WordCount() {  
  19.     }  
  20.    
  21.     public static void main(String[] args) throws Exception {  
  22.         Configuration conf = new Configuration();  
  23.         String[] otherArgs = (new GenericOptionsParser(conf, args)).getRemainingArgs();  
  24.         if(otherArgs.length < 2) {  
  25.             System.err.println("Usage: wordcount <in> [<in>...] <out>");  
  26.             System.exit(2);  
  27.         }  
  28.    
  29.         Job job = Job.getInstance(conf, "word count");  
  30.         job.setJarByClass(WordCount.class);  
  31.         job.setMapperClass(WordCount.TokenizerMapper.class);  
  32.         job.setCombinerClass(WordCount.IntSumReducer.class);  
  33.         job.setReducerClass(WordCount.IntSumReducer.class);  
  34.         job.setOutputKeyClass(Text.class);  
  35.         job.setOutputValueClass(IntWritable.class);  
  36.    
  37.         for(int i = 0; i < otherArgs.length - 1; ++i) {  
  38.             FileInputFormat.addInputPath(job, new Path(otherArgs[i]));  
  39.         }  
  40.    
  41.         FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length - 1]));  
  42.         System.exit(job.waitForCompletion(true)?0:1);  
  43.     }  
  44.    
  45.     public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {  
  46.         private IntWritable result = new IntWritable();  
  47.    
  48.         public IntSumReducer() {  
  49.         }  
  50.    
  51.         public void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {  
  52.             int sum = 0;  
  53.    
  54.             IntWritable val;  
  55.             for(Iterator i$ = values.iterator(); i$.hasNext(); sum += val.get()) {  
  56.                 val = (IntWritable)i$.next();  
  57.             }  
  58.    
  59.             this.result.set(sum);  
  60.             context.write(key, this.result);  
  61.         }  
  62.     }  
  63.    
  64.     public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {  
  65.         private static final IntWritable one = new IntWritable(1);  
  66.         private Text word = new Text();  
  67.    
  68.         public TokenizerMapper() {  
  69.         }  
  70.    
  71.         public void map(Object key, Text value, Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {  
  72.             StringTokenizer itr = new StringTokenizer(value.toString());  
  73.    
  74.             while(itr.hasMoreTokens()) {  
  75.                 this.word.set(itr.nextToken());  
  76.                 context.write(this.word, one);  
  77.             }  
  78.    
  79.         }  
  80.     }  
  81. }  

四.通过eclipse运行mapreduce

运行 MapReduce 程序前,务必将 /home/hadoop/hadoop/etc/hadoop 中将有修改过的配置文件(如伪分布式需要core-site.xmlhdfs-site.xml),以及log4j.properties复制到WordCount 项目下的 src文件夹(~/workspace/WordCount/src)中。

原因:

 

在使用 Eclipse 运行 MapReduce 程序时,会读取 Hadoop-Eclipse-PluginAdvanced parameters作为 Hadoop 运行参数,如果未进行修改,则默认的参数其实就是单机(非分布式)参数,因此程序运行时是读取本地目录而不是HDFS 目录,就会提示Input 路径不存在。

Exception in thread "main" org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input path does not exist: file:/home/hadoop/workspace/WordCountProject/input

所以需要将配置文件拷贝到项目中的 src 目录,来覆盖这些参数。让程序能够正确运行。log4j用于记录程序的输出日记,需要log4j.properties 这个配置文件,如果没有拷贝该文件到项目中,运行程序后在Console 面板中会出现警告提示

log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

这种情况不影响程序的正确运行的,但程序运行时无法看到任何提示消息,只能看到出错信息。

拷贝完成后,右键点击 WordCount 选择 refresh 进行刷新(不会自动刷新,需要手动刷新),可以看到文件结构如下所示:

 

 

点击工具栏中的 Run 图标,或者右键点击 Project Explorer 中的 WordCount.java,选择 Run As -> Run on Hadoop,就可以运行 MapReduce 程序了。不过由于没有指定参数,运行时会提示 "Usage: wordcount ",需要通过Eclipse设定一下运行参数。

右键点击刚创建的 WordCount.java,选择 Run As -> Run Configurations,在此处可以设置运行时的相关参数(如果 Java Application 下面没有 WordCount,那么需要先双击 Java Application)。切换到 "Arguments"栏,在Program arguments 处填写参数 "/input  /output"

注意:在环境下测试,如果没有"/",会提示如下错误信息:

Exception in thread "main" org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input path does not exist: hdfs://localhost:9000/user/hadoop/input

也可以直接在代码中设置好输入参数。可将代码 main() 函数的 String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); 改为(没有测试):

[java] view plain copy

  1. // String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();  
  2. String[] otherArgs=new String[]{"input","output"}; /* 直接设置输入参数 */  


设定参数后,运行程序,可以看到运行成功的提示,刷新DFS Location后也能看到输出的 output 文件夹。

 

五.在eclipse中导出可运行的jar包

1. 鼠标右键点击项目名称,并选择Export

2. 选择Java--> Runnable JAR file

3. 选择正确的项目配置信息,和输出路径以及重命名jar

4. 点击OK完成导出可运行jar(测试方法与运行Hadoop自带的Wordcount方法一样,不在赘述)

猜你喜欢

转载自my.oschina.net/u/3049601/blog/1812221