(服务器主机名CentOSQ)
①配置资源管理器
//编辑yarn-site文件
[root@CentOSQ ~]# vi /usr/hadoop-2.9.2/etc/hadoop/yarn-site.xml
//加如下列配置(注意下列配置我们的主机名是什么下列的配置和我们的主机名是一致的)
<!--配置MapReduce计算框架的核心实现Shuffle-洗牌-->
yarn.nodemanager.aux-services</name>
mapreduce_shuffle</value>
</property>
<!--配置资源管理器所在的目标主机-->
yarn.resourcemanager.hostname</name>
CentOSQ</value>
</property>
<!--关闭物理内存检查-->
yarn.nodemanager.pmem-check-enabled</name>
false</value>
</property>
<!--关闭虚拟内存检查-->
yarn.nodemanager.vmem-check-enabled</name>
false</value>
</property>
②配置MapReduce计算框架
//将mapred-site.xml.template文件使用移动命令mv 改成mapred-site.xml文件
[root@CentOSQ ~]# mv /usr/hadoop-2.9.2/etc/hadoop/mapred-site.xml.template /usr/hadoop-2.9.2/etc/hadoop/mapred-site.xml
[root@CentOSQ ~]# vi /usr/hadoop-2.9.2/etc/hadoop/mapred-site.xml
//在中加入下面的配置
<!--MapRedcue框架资源管理器的实现-->
mapreduce.framework.name</name>
yarn</value>
</property>
③启动计算服务
[root@CentOSQ ~]# start-yarn.sh
//使用jps查看我们的启动的服务
[root@CentOSQ ~]# jps
//我们的yarn框架启动后会有这么两个框架服务启动NodeManager、ResourceManager
1802 NodeManager
1711 ResourceManager
④可以访问ResourManager内嵌WebUI页面:http://CentOSQ:8088
我们需要保证在使用主机名访问的时候我们windows中的主机名映射是配置过的
背景
假设我们有如下的一张表,需要统计出每个版块被点击次数。
日志级别 类别 点击日期
INFO /product/xxxx1 2020-09-28 10:10:00
INFO /product/xxxx2 2020-09-28 12:10:00
INFO /cart/xxxx2 2020-09-28 12:10:00
INFO /order/xxxx 2020-09-28 12:10:00
如果我们可以将以上的日志看做成是数据库中的一张表,这个问题就可以使用以下SQL解决:
select category,sum(1) from t_click group by category
如果使用上面提到的MapReduce计算模型,我们可以使用Map完成group的功能,使用Reduce完成sum的功能。有如下数据格式
INFO /product/xxx/1?name=zhangsan 2020-09-28 10:10:00
INFO /product/xxx/1?name=zhangsan 2020-09-28 10:10:00
INFO /cart/xxx/1?name=lisi 2020-09-28 10:10:00
INFO /order/xxx/1?name=zhangsan 2020-09-28 10:10:00
INFO /product/xxx/1?name=zhaoliu 2020-09-28 10:10:00
INFO /cart/xxx/1?name=win7 2020-09-28 10:10:00
实现
①写Mapper逻辑
package com.baizhi.mr;
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;
/**
* 1、用户必须首先清楚 数据格式、存储位置 --读取数据方式 --Mapper写法?
* TextInputFormat:读取文件系统中文件本地系统、HDFS
* 字节偏移量 文本行
* 2、必须清楚的知道自己想干嘛? 按__类别__统计 __点击次数__值
* key value
*/
public class URLMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//获取一行的文本数据
String line = value.toString();
//以空格切分文本行数据
String[] split = line.split("\\s+");
//遍历以空格切分的单词进行输出
for (String s : split) {
context.write(new Text(s),new IntWritable(1));
}
}
}
②Reducer逻辑
package com.baizhi.mr;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* 1、你要对哪种Mapper的输出结果汇总 -- 决定Reducer输入的Key和Value类型
*
* 2、你要知道最终输出结果以哪种格式写出去,输出Key/Value格式用户只需要关注他的toString即可
*
* TextOutputFormat 将结果写出到文件系统:本地、HDFS
*/
public class URLReducer extends Reducer<Text, IntWritable, Text,IntWritable> {
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int total=0;
for (IntWritable value : values) {
total+=value.get();
}
context.write(key,new IntWritable(total));
}
}
③封装Job对象
package com.baizhi.mr;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
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.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
//com.baizhi.mr.URLCountApplication
public class URLCountApplication extends Configured implements Tool {
public int run(String[] strings) throws Exception {
//1.创建一个job对象
Configuration conf =getConf();
Job job = Job.getInstance(conf, "URLCountApplication");
//打包任务发布需要添加的代码
job.setJarByClass(URLCountApplication.class);
//2.设置数据格式
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
//3.设置从那个文件里读取的数据路径
TextInputFormat.addInputPath(job,new Path("/logs/word"));
//系统自己创建的的输出路径 如果系统文件存在则自动放弃(这样做是为了防止数据的覆盖)
TextOutputFormat.setOutputPath(job,new Path("/logs/wordcount"));
//4.设置处理逻辑
job.setMapperClass(URLMapper.class);
job.setReducerClass(URLReducer.class);
//5.设置输出的key value
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6.提交
return job.waitForCompletion(true)?1:0;
}
public static void main(String[] args) throws Exception {
ToolRunner.run(new URLCountApplication(),args);
}
}
远程部署
需要在job当中添加如下代码
job.setJarByClass(URLCountApplication.class);
打包程序
设置程序的类加载路径,因为任务是打好jar包以后使用hadoop jar命令提交的.
[root@CentOSQ ~]# hadoop jar Hadoop_MR-1.0-SNAPSHOT.jar com.baizhi.mr.URLCountApplication
//或者如下
[root@CentOSQ ~]# yarn jar Hadoop_MR-1.0-SNAPSHOT.jar com.baizhi.mr.URLCountApplication