wordcount实例
1.mapper
package com.apollo.mr.wordcount;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* 4个泛型中,前两个是指定mapper输入数据的类型,KEYIN是输入的key的类型,VALUEIN是输入的value的类型,KEYOUT是输出key的类型,VALUEOUT是输出out的类型
* map 和 reduce 的数据输入输出都是以 key-value对的形式封装的
* 默认情况下,框架传递给我们的mapper的输入数据中,key是要处理的文本中一行的起始偏移量,这一行的内容作为value
*/
public class WCMapper extends Mapper<LongWritable,Text,Text,LongWritable> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//具体业务逻辑就写在这个方法体中,而且我们业务要处理的数据已经被框架传递进来,在方法的参数中 key-value
//key 是这一行数据的起始偏移量 value 是这一行的文本内容
String line = value.toString();
//对这一行的文本按特定分隔符切分
String[] words = line.split(" ");
//遍历这个单词数组输出为kv形式 k:单词 v : 1
for(String word : words){
context.write(new Text(word),new LongWritable(1));
}
}
}
2.Reducer
package com.apollo.mr.wordcount;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* 框架在map处理完成之后,将所有kv对缓存起来,进行分组,然后传递一个组<key,valus{}>,调用一次reduce方法
* <hello,{1,1,1,1,1,1.....}>
*/
public class WCReducer extends Reducer<Text,LongWritable,Text,LongWritable> {
@Override
protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
long count = 0;
//遍历value的list,进行累加求和
for(LongWritable value : values){
count += value.get();
}
//输出这一个单词的统计结果
context.write(key,new LongWritable(count));
}
}
3.Job
package com.apollo.mr.wordcount;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
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;
/**
* 用来描述一个特定的作业
* 比如,该作业使用哪个类作为逻辑处理中的map,哪个作为reduce
* 还可以指定该作业要处理的数据所在的路径
* 还可以指定改作业输出的结果放到哪个路径
* ....
*/
public class WCRunner {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
Job wcjob = Job.getInstance(conf);
//设置整个job所用的那些类在哪个jar包
wcjob.setJarByClass(WCRunner.class);
//本job使用的mapper和reducer的类
wcjob.setMapperClass(WCMapper.class);
wcjob.setReducerClass(WCReducer.class);
//本job使用的mapper和reducer的类
wcjob.setOutputKeyClass(Text.class);
wcjob.setOutputKeyClass(LongWritable.class);
//指定mapper的输出数据kv类型
wcjob.setMapOutputKeyClass(Text.class);
wcjob.setMapOutputValueClass(LongWritable.class);
//指定要处理的输入数据存放路径
FileInputFormat.setInputPaths(wcjob,new Path("/wc/srcdata"));
//指定处理结果的输出数据存放路径
FileOutputFormat.setOutputPath(wcjob,new Path("/wc/output"));
//将job提交给集群运行 ,true打印执行过程
wcjob.waitForCompletion(true);
}
}
生成jar包放到集群节点上,shell命令
[hadoop@hadoop100 software]$ hadoop jar apollo.jar com.apollo.mr.wordcount.WCRunner
Job的提交逻辑及YAR框架的技术
hadoop集群中主要进程有
master: NameNode, ResourceManager,
slaves: DataNode, NodeManager, RunJar, MRAppMaster, YarnChild
其中 RunJar, MRAppMaster,YarnChild与随着某个job的创建而创建,随着job的完成而终止。它们的作用分别是:
RunJar:完成job的初始化,包括获取jobID,将jar包上传至hdfs等。
MRAppMaster:每个job一个进程,主要跟踪job的运行情况,向RM申请资源等。
YarnChild:运行具体的map/reduce task。
job启动过程:
ResourceManage,NodeManager->RunJar->MRAppMaster->YarnChild
job退出过程:
YarnChild->MRAppMaster->RunJar
即所有的map/reduce均完成后,MRAppMaster才退出,最后RunJar退出,job完成。
YARN 资源调度
ResourceManager 监控作用-------管理 NodeManager
节点/进程 节点/进程
MAPREDUCE
MRAppMaster 监控作用-------管理 YarnChild
节点/进程 节点/进程
1. Job客户端JobClient在job.waitforcompletion()方法后启动一个RunJar的进程,RunJar向resourceManager 申请执行一个job。
2. resourceManager节点的JobTracker返回job相关资源要存放的路径(HDFS)stagging-dir
3. RunJar将jar和job相关的资源提交到指定的HDFS目录下,一般路径是HDFS /tmp/xx/xx./yarn-stagging/jobID/
4. RunJar汇报提交结果给resourceManager。
5. resourceManager将本job加入到任务队列中。并规定本job放到哪些nodemanager运行。
6. nodemager节点的TaskTracker通过心跳机制检查任务队列,发现有新任务,nodemanger领取任务。
7. nodemanger初始化运行环境。分配运行资源容器container。同时取HDFS上取jar和job相关的资源。
8. resourceManager启动MRAppMaster。
9. MRAppMaster向resourceManager(RM)注册,获取哪些nodemanger可以用。
10. MRAppMaster在nodemanger的container里启动map task,进程是YarnChild
11. MRAppMaster在nodemanger的container里启动reduce task,进程是YarnChild
12. job完成后向RM注销自己。
MR程序的提交模式
修改的hadoop源代码:[这里写链接内容](http://download.csdn.net/detail/wang11yangyang/9888021)
*本地测试环境(windows):*
1.在window下配置hadoop环境变量HADOOP_HOME、PATH
java路径有空格会报错如:D:\Program Files (x86)\Java
所以,JAVA_HOME=D:\PROGRA~1\Java\jdk1.8.0_31就是 Program Files (x86)目录的dos文件名模式下的缩写长于8个字符的文件名和文件夹名,都被简化成前面6个有效字符,后面~1,有重名的就 ~2,~3
2.复制winutils.exe到window的hadoop目录bin目录
3.修改源码,在src下添加如下两个类来取代hadoop的原来的类
org.apache.hadoop.io.nativeio.NativeIO.java
org.apache.hadoop.mapred.YARNRunner.java
4.MR调用的代码需要改变:
a.src不能有服务器的hadoop配置文件
b.手动添加如下代码:
Configuration config =new Configuration();
config.set("fs.defaultFS", "hdfs://node1:8020");
config.set("yarn.resourcemanager.hostname", "node1");
*本地测试(Linux)*
1.src不能有服务器的hadoop配置文件
*服务器环境:*
*1.在本地直接调用,执行过程在服务器上(真正企业运行环境)*
a.在window下配置hadoop环境变量HADOOP_HOME、PATH
b.将工程打成jar包,放在本地。
c.修改源码(windows需要修改源码,linux不需要),在src下添加如下两个类来取代hadoop的原来的类
org.apache.hadoop.io.nativeio.NativeIO.java
org.apache.hadoop.mapred.YARNRunner.java
d.增加一个属性:
config.set("mapred.jar", "C:\\Users\\Administrator\\Desktop\\wc.jar");
e.本地执行main
*2.直接在服务器上,使用命令的方式提交,执行过程也在服务器上*
a.将工程打成jar包,上传到服务器,
b.然后用hadoop命令提交 hadoop jar wc.jar cn.itcast.hadoop.mr.wordcount.WCRunner