1.本地测试
Mapreduce编写规范
用户编写的程序分成三个部分:Mapper、Reducer和Driver。
环境准备
(1)创建maven工程
(2)在pom.xml文件中添加如下依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>
(3)在项目的src/main/resources目录下,新建一个文件,命名为“log4j2.xml”,在文件中填入。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" strict="true" name="XMLConfig">
<Appenders>
<!-- 类型名为Console,名称为必须属性 -->
<Appender type="Console" name="STDOUT">
<!-- 布局为PatternLayout的方式,
输出样式为[INFO] [2018-01-22 17:34:01][org.test.Console]I'm here -->
<Layout type="PatternLayout"
pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c{10}]%m%n" />
</Appender>
</Appenders>
<Loggers>
<!-- 可加性为false -->
<Logger name="test" level="info" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
<!-- root loggerConfig设置 -->
<Root level="info">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
(4)编写程序
(4.1)编写Mapper类
package com.atguigu.mapreduce;
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, 输入数据的key的类型 表示读取文件的位置(偏移量) LongWritable
* VALUEIN, 输入数据的value的类型 表示文件的一行内容 Text
*
* KEYOUT, 输出数据的key的类型 表示就是一个单词 Text
* VALUEOUT 输出数据的value的类型 表示就是1 IntWritable
*/
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
/**
* map阶段的核心处理方法
* @param key 输入数据的key
* @param value 输入数据的value 一行数据
* @param context 对输出数据的包装对象
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//为了更方便的操作输入数据,将value的类型转化为String
String linecontext = value.toString();
//对当前行数据进行分割
String[] lineArr = linecontext.split(" ");
//遍历集合 组织输出数据
for (String word : lineArr) {
//准备输出数据的key
Text outkey = new Text(word);
//准备输出数据的value
IntWritable outvalue = new IntWritable(1);
//将数据写出
context.write(outkey,outvalue);
}
}
}
(4.2)编写Reducer类
package com.atguigu.mapreduce;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* KEYIN, 输入内容的key的类型 表是就是Map阶段的输出数据的key Text
* VALUEIN, 输入内容的value的类型 表是就是Map阶段的输出数据的value IntWritable
*
* KEYOUT, 输出数据的key的类型 表示一个单词 Text
* VALUEOUT 输出数据的value的类型 表示单词出现的次数 IntWritable
*/
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
/**
*
* @param key 输入数据的key 一个单词
* @param values 表示相同的key所对应的一组value
* @param context 输出数据的包装对象
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
// 初始化单词出现次数
int sum = 0;
// 遍历当前相同key对应的values 进行累加操作
for (IntWritable value : values) {
sum+=value.get();
}
// 将累加结果写出
context.write(key, new IntWritable(sum));
}
}
(4.2)编写Driver驱动类
package com.atguigu.mapreduce;
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;
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1.创建Configuration对象
Configuration conf = new Configuration();
//2.创建Job对象(用来包装MR作业的对象)
Job job = Job.getInstance(conf);
//3.给Job关联当前的驱动类
job.setJarByClass(WordCountDriver.class);
//4.给Job关联Mapper类和Reducer类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//5. 指定job执行的时候的Map阶段的输出数据的类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//6.指定job最终的输出结果的类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//7.指定要分析的文件的输入路径和输出路径
// 本地运行
FileInputFormat.setInputPaths(job, new Path("D:\idea workspace\Mapreduce\src\input\wc.input"));
FileOutputFormat.setOutputPath(job, new Path("D:\idea workspace\Mapreduce\src\output"));
// 集群运行
/*FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));*/
//8.提交作业
job.waitForCompletion(true);
}
}
运行测试
2.集群测试
集群测试需要注意的是
2.1编写的Mapper类,Reducer类不用修改,只需修改Driver驱动类中的第7部分即可
2.2将程序打成JAR包,然后上传到hadoop集群中(补充一下如何从hadoop集群上下载文件 sz 要下载的文件)
2.3启动集群
2.4 cd 到JAR包上传的路径位置,执行 hadoop jar JAR名字 全类名(在idea中点击类名直接copy reference) 文件输入路径 文件输出路径
(hadoop jar Mapreduce-1.0-SNAPSHOT.jar com.atguigu.mapreduce.WordCountDriver /wc.input /output)
2.5 浏览器中输入:http://hadoop102:9870 (每个人的配置的地址不一样) Web端查看HDFS的NameNode,查看HDFS上存储的数据信息
3.在windows上向集群提交任务(了解)
添加必要的配置信息
package com.atguigu.mapreduce;
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;
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1.创建Configuration对象
Configuration conf = new Configuration();
//设置HDFS NameNode的地址
configuration.set("fs.defaultFS", "hdfs://hadoop102:9820");
// 指定MapReduce运行在Yarn上
configuration.set("mapreduce.framework.name","yarn");
// 指定mapreduce可以在远程集群运行
configuration.set("mapreduce.app-submission.cross-platform","true");
//指定Yarn resourcemanager的位置
configuration.set("yarn.resourcemanager.hostname","hadoop103");
//2.创建Job对象(用来包装MR作业的对象)
Job job = Job.getInstance(conf);
//3.给Job关联当前的驱动类
// job.setJarByClass(WordCountDriver.class);
//打包,并将Jar包设置到Driver中
job.setJar("D:IdeaProjectsmapreduce argetmapreduce-1.0-SNAPSHOT.jar");
//4.给Job关联Mapper类和Reducer类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//5. 指定job执行的时候的Map阶段的输出数据的类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//6.指定job最终的输出结果的类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//7.指定要分析的文件的输入路径和输出路径
// 本地运行
FileInputFormat.setInputPaths(job, new Path("D:\idea workspace\Mapreduce\src\input\wc.input"));
FileOutputFormat.setOutputPath(job, new Path("D:\idea workspace\Mapreduce\src\output"));
// 集群运行
/*FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));*/
//8.提交作业
job.waitForCompletion(true);
}
}
(2)编辑任务配置
1)检查第一个参数Main class是不是我们要运行的类的全类名,如果不是的话一定要修改!
2)在VM options后面加上 :-DHADOOP_USER_NAME=atguigu
3)在Program arguments后面加上两个参数分别代表输入输出路径,两个参数之间用空格隔开。如:hdfs://hadoop102:9820/input hdfs://hadoop102:9820/output
(3)打包,并将Jar包设置到Driver中
主要修改了两个位置
1.configuration的配置
2 设置jar加载路径
job.setJar("D:IdeaProjectsmapreduce argetmapreduce-1.0-SNAPSHOT.jar");