电商实战——Hadoop实现(1)
## 项目要求
- 根据电商日志文件,分析:
-
统计页面浏览量(每行记录就是一次浏览)
-
统计各个省份的浏览量 (需要解析IP)
-
日志的ETL操作(ETL:数据从来源端经过抽取(Extract)、转换(Transform)、加载(Load)至目的端的过程)
- 为什么要ETL:没有必要解析出所有数据,只需要解析出有价值的字段即可。本项目中需要解析出:ip、url、pageId(topicId对应的页面Id)、country、province、city
注意:
项目中所使用到的数据如下:
注意:如果直接将数据拖动到虚拟机中,会存在只能传输部分数据的问题,导致实验结果不完全不正确,所以,采用xshell进行传输数据文件!!!
实现步骤:
idea中创建好项目,首先实现 统计页面浏览量(每行记录就是一次浏览)
创建一个PageViewMapper类
-
继承自 Mapper 类。
-
重写了 map 方法,该方法接收输入键值对,输出中间键值对。
-
这里的 map 方法简单地为每条输入记录输出一个键为 “line” 的键值对,并将值设置为 1,意味着每条记录都被视为一个页面浏览。
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; public class PageViewMapper extends Mapper<LongWritable, Text, Text, IntWritable> { @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { context.write(new Text("line"), new IntWritable(1)); } }
创建一个PageViewReducer类
- 继承自 Reducer 类。
- 重写了 reduce 方法,该方法接收中间键值对的键和值的迭代器,输出最终的键值对。
- 在 reduce 方法中,对所有具有相同键的值进行求和,得到总的页面浏览量,并输出。
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class PageViewReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
创建一个LogAnalysisDriver类
- 包含 main 方法,是程序的入口点。
- 配置 Hadoop 作业,设置作业的名称、类路径、映射器、合并器和归约器类。
- 设置作业的输入和输出路径。
- 启动作业,并根据作业的完成状态返回相应的退出代码。
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;
public class LogAnalysisDriver {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.err.println("Usage: LogAnalysisDriver <input path> <output path>");
System.exit(-1);
}
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "Page View Count");
job.setJarByClass(LogAnalysisDriver.class);
job.setMapperClass(PageViewMapper.class);
job.setCombinerClass(PageViewReducer.class);
job.setReducerClass(PageViewReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}}