hadoop作为分布式计算三大框架之一,在现实的应用中,具有重要的地位。本文通过经典的词频统计的实例,来说明如何在windows10下进行基于Hadoop的程序开发和调试,并就自己遇到的“坑“详细说明一下解决方法。
1. 具体需要完成的工作如下:
首先,你要有一个linux环境,hadoop无法运行在windows系统之上的,你可以在window上安装虚拟机,并在虚拟机上安装linux系统(或者采用cygwin,本文不介绍);
然后,你需要安装并配置一个hadoop集群;
其次,在windows下,对eclipse进行配置,使其能够进行hadoop开发;
最后,创建hadoop工程,编写代码并调试。
2. 准备工作
2.1. 安装虚拟机、linux系统和hadoop集群
所使用的软件为VirtualBox+Centos 7+ Hadoop2.6,hadoop集群为伪分布式方式,具体可参考 http://blog.csdn.net/yongge1981/article/details/78737523中相关部分;
需要注意core-site.xml中加入如下配置:
<property>
<name>fs.defaultFS</name>
<value>hdfs://192.168.56.109:9000</value>
</property>
mapred-site.xml中加入如下配置:
<property>
<name>mapred.job.tracker</name>
<value>192.168.56.109:9001</value>
</property>
2.2 windows10下开发环境配置
安装hadoop,就是将hadoop-2.6.0.tar.gz进行解压,比如解压到d盘根目录下,然后配置环境变量如下:
eclipse安装hadoop插件,下载hadoop-eclipse-plugin-2.6.0.jar,并将其放到eclipse文件夹下的plugins目录下,并进行配置如下:
打开Eclipse,选择Window->Preferences,选择Hadoop Map/Reduce,做如下设置:
注意:将hadoop的bin目录下的hadoop.dll拷贝到C:\Windows\System32下,注意版本要一致。
配置Map/Reduce Locations
在eclipse窗口下,选择Window->Show view->other, 选择MapReduce Tools下的Map/Reduce Locations,然后,在打开的窗口中,点击右键->new hadoop location,会打开如下窗口,然后设置Map/Reduce(V2) Master和DFS Master,如下所示,注意:要和hadoop集群保持一致,否则在代码调试会报错。
成功配置Map/Reduce Locations后,能够在DFS Locations下看到远程hadoop集群的dfs文件系统中的目录及文件,如下图所示:
2.3 创建hadoop工程,并编写调试代码
在eclipse窗口下,选择File->new->other,选择建立Map/Reduce Project,如下图所示,
然后,新建一个WordCount类,其代码如下:
package org.xh.examples;
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 {
// Mapper类
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{
// new一个值为1的整数对象
private final static IntWritable one = new IntWritable(1);
// new一个空的Text对象
private Text word = new Text();
// 实现map函数
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
// 创建value的字符串迭代器
StringTokenizer itr = new StringTokenizer(value.toString());
// 对数据进行再次分割并输出map结果。初始格式为<字节偏移量,单词> 目标格式为<单词,频率>
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
// Reducer类
public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
// new一个值为空的整数对象
private IntWritable result = new IntWritable();
// 实现reduce函数
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);
// 输出reduce结果
context.write(key, result);
}
}
// 主函数
public static void main(String[] args) throws Exception {
// 获取配置参数
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
// 检查命令语法
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);
// 注册Mapper类
job.setMapperClass(TokenizerMapper.class);
// 注册合并类
job.setCombinerClass(IntSumReducer.class);
// 注册Reducer类
job.setReducerClass(IntSumReducer.class);
// 注册输出格式类
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 设置输入输出路径
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
// 运行程序
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}代码来源:https://www.cnblogs.com/muchen/p/6881353.html
设置运行参数,如下图所示:
调试的时候遇到一个问题,即程序会将windows用户名提交到hadoop集群上,而hdfs目录权限会是得的不能读写文件系统,解决方案一就是将windows用户名改成hadoop集群的用户名。