Hadoop开发实例 使用Eclipse实现WordCount

在学习Hadoop中,WordCount是许多人接触的第一个MapReduce程序,我也不例外。通过在网络上学习找到了不少帖子,但大多数是使用终端运行hadoop jar WordCount.jar实现的。本文将介绍如何使用Eclipse开发并运行WordCount。

开发环境

  • 系统:MacOS 10.14.1
  • Hadoop:2.7.0
  • Java:1.8.0
  • Eclipse:4.6.2

配置Eclipse

添加hadoop-eclipse-plugin插件

新安装的Eclipse通常是无法直接新建MapReduce程序,需要添加hadoop-eclipse-plugin插件,下载地址
此处以macOS为例。

  1. 先下载hadoop_eclipse_plugin插件
  2. 进入到eclipse的dropins目录
    在Finder中找到应用程序,然后找到eclipse.这时eclipse显示的是一个app,而不是一个目录。右键点击后,打开选择显示包内容,就可以找到eclipse的应用程序目录了
  3. 把hadoop_eclipse_plugin.jar放进dropins文件夹内。
  4. 重启eclipse,打开window-> show view-> other-> MapReduce Tools,选择Map/Reduce Locations

与Hadoop集群建立连接

点击Eclipse的Map/Reduce Locations面板在面板中单击右键,选择New Hadoop Location。
MapReduce location
在弹出来的General选项面板中,General 的设置要与 Hadoop 的配置一致。一般两个 Host值是一样的。如果是在本机搭建hadoop伪分布式,填写 localhost 即可,这里使用的是Hadoop伪分布,DFS Master 的 Port 改为 9000。Map/Reduce(V2) Master 的 Port 用默认的即可,Location Name 随意填写。
MapReduce location

操作HDFS文件

配置好后,点击Project Explorer 中的DFS Location就能直接查看 HDFS 中的文件列表,双击可以查看内容,右键点击可以上传、下载、删除 HDFS 中的文件。
HDFS
HDFS_upload_download
当程序运行完成后,会生成一个output文件夹,通常运行完成后不能马上看到,此时可以尝试,右键点击DFS Locations后Reconnect或重启Eclipse。

使用Eclipse实现WordCount

Create Project

点击File菜单,选择New->Project
new_project_wordcount
选择MapReduce wizard,后点击next。
mapreduce wizard
Project Name随意填写,然后点finish。
new mapreduce project

Create WordCount.java

如普通Project一样,创建一个java程序后,复制如下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {

/**
* LongWritable, IntWritable, Text 均是 Hadoop 中实现的用于封装 Java
* 数据类型的类,这些类实现了WritableComparable接口,
* 都能够被串行化从而便于在分布式环境中进行数据交换,你可以将它们分别视为long,int,String 的替代品。
*/
private final static IntWritable one = new IntWritable(1); // 值为1
private Text word = new Text();

public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString()); // 对字符串进行切分
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}

public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();

public void reduce(Text key, Iterable<IntWritable> values, Context context)
throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}

public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
// String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
String[] otherArgs = {"/input", "/output"};
if (otherArgs.length != 2) {
System.err.println("Usage: wordcount <in> <out>");
System.exit(2);
}
Job job = new Job(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.setInputDirRecursive(job, true);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}

}

在Eclipse运行WordCount.java

如前文所说,若要在hadoop上运行此project需要封装成jar包。若需要直接在Eclipse右键运行的话还需要做一下配置。
运行 MapReduce 程序前,务必将 /usr/local/Cellar/hadoop/2.7.0/libexec/etc/hadoop 中将有修改过的配置文件(如伪分布式需要core-site.xml 和 hdfs-site.xml),以及log4j.properties复制到WordCount 项目下的src文件夹(~/workspace/WordCount/src)中。如下图
mapreduce 配置

这是因为在使用 Eclipse 运行 MapReduce 程序时,会读取 Hadoop-Eclipse-Plugin 的Advanced parameters作为 Hadoop 运行参数,如果未进行修改,则默认的参数其实就是单机(非分布式)参数,因此程序运行时是读取本地目录而不是HDFS目录,就会提示Input路径不存在。报如下图错误
word count error
配置好以上文件后,就可以运行普通java程序一样右键run了,不同的是所输出的结果会出现的HDFS上,而输出路径及输入数据集的路径在在源代码中String[] otherArgs指定。
word count output

Have a nice day!