首先介绍下开发环境,Hadoop部署在阿里云上,本地用IDEA开发,目的是使用MR做一个简单的WC。
1、Mapper、Reducer及Driver相关代码
1.1 Mapper业务代码
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* keyin Map任务读取数据的key类型,offset,是每行数据起始位置的偏移量,Long
* Valuein Map任务读数据的value类型,其实就是一行行的字符串,String类型
* hello world welcome
* hello welcome
* keyout map方法自定义实现输出的key类型,String
* valueout map方法自定义实现的value类型,Integer类型
*/
public class WordCountMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 把value对应的行数据按照指定的分隔符拆开
String[] words = value.toString().split("\t");
for(String word : words){
context.write(new Text(word),new IntWritable(1));
}
}
}
1.2 Reducer业务代码
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
import java.util.Iterator;
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
/**
* (hello,1) (world,1)
* (hello,1) (world,1)
* (welcome,1)
* <p>
* map的输出到reduce端,是按照相同的key分发到一个reduce上去执行的
* <p>
* reduce1: (hello,1) (hello,1) (hello,1) --> (hello,<1,1,1>)
* reduce2: (world,1) (world,1) (world,1) --> (world, <1,1,1>)
* reduce3: (welcome,1) --> (welcome,<1>)
*
* @param key
* @param values
* @param context
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int count = 0;
Iterator<IntWritable> iterator = values.iterator();
while (iterator.hasNext()) {
IntWritable value = iterator.next();
count += value.get();
}
context.write(key,new IntWritable(count));
}
}
1.3 Driver业务代码
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
/**
* 使用MR统计HDFS上的文件对应的词频
*/
public class WordCountApp {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// System.setProperty("HADOOP_USER_NAME","root");
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS", "hdfs://121.**.***.81:8020/");
// configuration.set("dfs.client.use.datanode.hostname", "true");
// 创建一个job
Job job = Job.getInstance(configuration);
// 设置job对应的参数:主类
job.setJarByClass(WordCountApp.class);
// 设置job对应的参数:自定义Mapper和Reducer类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
// 设置Job对应的参数:Mapper输出key和value的类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 设置Job对应的参数:Reducer输出key和value的类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 设置Job对应的参数:Mapper输出key和value的类型,作业输入和输出的路径
FileInputFormat.setInputPaths(job, new Path("/wordcount/input"));
FileOutputFormat.setOutputPath(job, new Path("/wordcount/output"));
// 提交job
boolean res = job.waitForCompletion(true);
System.exit(res ? 0 : -1);
}
}
2、相关错误汇总及解决办法
2.1 第一个错误
解决办法下载
解决办法:
(1) 下载winutils,注意需要与hadoop的版本相对应。
hadoop2.2版本可以在这里下载 github.com/srccodes/ha…
hadoop2.6版本可以在这里下载 github.com/amihalik/ha…
由于配置的测试集群是hadoop2.6.0,所以我在这里下载的是2.6.0版本的。下载后,将其解压。
(2) 配置环境变量
增加系统变量HADOOP_HOME,值是下载的zip包解压的目录,我这里解压后将其重命名为hadoop-common-2.6.0
在系统变量path里增加%HADOOP_HOME%\bin
重启电脑,使环境变量配置生效,上述问题即可解决。
2.2 第二个错误
解决办法,在上一个基础上删除所有文件夹内部的hadoop.dll文件
2.3 第三个错误
解决办法,自定义NativeIO类,在access方法处之间返回true
2.4 第四个错误
提示Windows用户权限不足。
加一行代码,用Linux内部操作Hadoop的用户来操作
System.setProperty("HADOOP_USER_NAME","root");
2.5 第五个错误
连接超时 解决方法:
configuration.set("dfs.client.use.datanode.hostname", "true");