下载hadoop-eclipse-plugin-2.7.3.jar包(从网上下载对应你安装的hadoop版本)
下载好之后解压把hadoop-eclipse-plugin-2.7.3.jar复制到你安装eclipse的路径的plugins这个文件夹下(例如我的:D:\Tools\Eclipse-JEE-Oxygen-R-win32-x86_64\eclipse\plugins)
然后启动eclipse,在主菜单中选择Window->Preferences,在弹出的对话框中选择左边的Hadoop Map/Reduce,然后在右边的Hadoop installation directory中填入Hadoop的安装目录,如下图所示:
!注意是Hadoop的安装目录,而不是这个jar包的安装目录!
在主菜单中选择Window->Show View->Other,在弹出的对话框中找到并展开MapReduce Tools,然后选择Map/Reduce Locations,如下图所示:
出现Map/Reduce Locations子窗口,如下图所示:
点击右边那头蓝色大象出现如下窗口:
Location name 自己取一个
左边的Master默认的不用修改
DFS Master host 的 Port 填之前配置过得 9000
说明:Map/Reduce (V2) Master的Host和port是Yarn的主机和端口号,默认端口号是50020。DFS Master的Host和Port需要根据core-site.xml文件配置。默认端口号是9000。
配置正确后点击finish,主窗口会看到新增的Hadoop Location,如下图所示:
到此在Eclipse中搭建MapReduce开发环境的配置完成!
新建项目 File–New–Other–Map/Reduce Project 命名为WordCount:
包 com.hadoop.worldcount 创建类 MyWordCount
复制以下代码放入类:
package com.hadoop.worldcount;
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.LongWritable;
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;
public class MyWordCount {
public static class TokenizerMapper extends Mapper {
/**
* Mapper中的map方法:
* void map(K1 key, V1 value, Context context)
* 映射一个单个的输入k/v对到一个中间的k/v对
* 输出对不需要和输入对是相同的类型,输入对可以映射到0个或多个输出对。
* Context:收集Mapper输出的对。
* Context的write(k, v)方法:增加一个(k,v)对到context
* 程序员主要编写Map和Reduce函数.这个Map函数使用StringTokenizer函数对字符串进行分隔,通过write方法把单词存入word中
* write方法存入(单词,1)这样的二元组到context中
*/
@Override
protected void map(LongWritable key, Text value, Mapper.Context context)
throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
context.write(new Text(itr.nextToken()), new IntWritable(1));
}
}
}
public static class IntSumReducer extends Reducer {
/**
* Reducer类中的reduce方法:
* void reduce(Text key, Iterable values, Context context)
* 中k/v来自于map函数中的context,可能经过了进一步处理(combiner),同样通过context输出
*/
@Override
protected void reduce(Text key, Iterable values,
Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
context.write(key, new IntWritable(sum));
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
/**
* Configuration:map/reduce的j配置类,向hadoop框架描述map-reduce执行的工作
*/
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "myWordCount"); //设置一个用户定义的job名称
job.setJarByClass(MyWordCount.class);
job.setMapperClass(TokenizerMapper.class); //为job设置Mapper类
job.setCombinerClass(IntSumReducer.class); //为job设置Combiner类
job.setReducerClass(IntSumReducer.class); //为job设置Reducer类
job.setOutputKeyClass(Text.class); //为job的输出数据设置Key类
job.setOutputValueClass(IntWritable.class); //为job输出设置value类
FileInputFormat.addInputPath(job, new Path("hdfs://localhost:9000/user/root/input/world.txt"));
FileOutputFormat.setOutputPath(job, new Path("hdfs://localhost:9000/user/root/output"));
System.exit(job.waitForCompletion(true) ?0 : 1); //运行job
}
}
新建文件 File–New–file 命名为 log4j.properties 内容如下:
log4j.rootLogger=debug,stdout,R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=mapreduce_test.log
log4j.appender.R.MaxFileSize=1MB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
log4j.logger.com.codefutures=DEBUG
刚配置部署的Hadoop还没创建输入和输出目录,先在hdfs上建个文件夹
如果hadoop服务已经处于启动状态需要先停止 Hadoop-2.7.3\sbin 目录下 输入 stop-all.cmd
cmd进入到hadoop的bin目录下分别创建:
hdfs dfs -mkdir –p /user/root/input
hdfs dfs -mkdir -p /user/root/output
然后转到 Hadoop-2.7.3\sbin 下,输入start-all.cmd,启动hadoop服务。
(注意区分 bin 和 sbin)
然后DFS Location下右击大象hadoop 点击Reconnect 点击refresh 你会看到出现了文件夹:
这个路径对应我们创建的MyWordCount类里面的这两个输入输出路径:
FileInputFormat.addInputPath(job, new Path("hdfs://localhost:9000/user/root/input/world.txt"));
FileOutputFormat.setOutputPath(job, new Path("hdfs://localhost:9000/user/root/output"));
上面一个是需要读取的文件的路径,下面一个是用来接收输出结果的路径(对应你在服务上创建的路径)
在本地建立一个txt文件,用来上传到服务作为输入文件:
输入一些单词
创建一个类File
复制以下代码:
package com.hadoop.worldcount;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
public class File {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws Exception {
String localSrc = "D:\\Tools\\hadoop\\LocationFile\\world.txt";//本地文件
String dst = "hdfs://localhost:9000/user/root/input/world.txt";//复制到hdfs目录下
InputStream in = new BufferedInputStream(new FileInputStream(localSrc));
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(dst), conf);
OutputStream out = fs.create(new Path(dst), new Progressable() {//进度条信息
public void progress() {
System.out.print(".");
}
});
IOUtils.copyBytes(in, out, 4096, true);//复制
}
}
(注意路径对应自己的路径,确保无误)
然后右击File类 Run As —— run on hadoop:
运行成功的话,在DFS Location中右击refresh 在input下会出现 txt:
这时候我们就可以运行MyWordCount类了,右击MyWordCount类 Run As —— run on hadoop:
如果运行成功,在output下会出现两个文件:
可以看到结果,hello 单词有3个 java 2个 world 1个
以上wordcount的demo就完成了!