1.需求:

  现有一些原始日志需要做增强解析处理,流程:

  1、 从原始日志文件中读取数据(日志文件:https://pan.baidu.com/s/12hbDvP7jMu9yE-oLZXvM_g)

  2、 根据日志中的一个URL字段到外部知识库中获取信息增强到原始日志

  3、 如果成功增强,则输出到增强结果目录;如果增强失败,则抽取原始数据中URL字段输出到待爬清单目录

2.需求分析:

  程序的关键点是要在一个mapreduce程序中根据数据的不同输出两类结果到不同目录,这类灵活的输出需求可

以通过自定义outputformat来实现

3.需求实现: 

技术实现要点:

  1、 在mapreduce中访问外部资源(知识数据库)

  2、 自定义outputformat,改写其中的recordwriter,改写具体输出数据的方法write()


代码实现:

1.数据库获取数据的工具类:

  1.首先启动数据库服务(192.168.232.201):service mysql start

  2.使用远程客户端连接数据库工具Navicat操作数据库:导入创建url_rule表语句和导入该表数据

  3.创建表语句及其数据下载:https://pan.baidu.com/s/1k74-o8wbFp5QC8Ee4Fu1YQ

  

package cn.bigdata.hdfs.LogEnhance;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Map; public class DBLoader {
public static void dbLoader(Map<String, String> ruleMap) throws Exception { Connection conn = null;
Statement st = null;
ResultSet res = null; try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://192.168.232.201:3306/mysql", "root", "root");
st = conn.createStatement();
res = st.executeQuery("select url,content from url_rule");
while (res.next()) {
ruleMap.put(res.getString(1), res.getString(2));
}
} finally {
try{
if(res!=null){
res.close();
}
if(st!=null){
st.close();
}
if(conn!=null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}

2.自定义一个outputformat继承自FileOutputFormat,实现getRecordWriter方法:

package cn.bigdata.hdfs.LogEnhance;
import java.io.IOException;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/**
* maptask或者reducetask在最终输出时,先调用OutputFormat的getRecordWriter方法拿到一个RecordWriter
* 然后再调用RecordWriter的write(k,v)方法将数据写出
*/
public class LogEnhanceOutputFormat extends FileOutputFormat<Text, NullWritable> { @Override
public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext context) throws IOException, InterruptedException {
///拿到一个文件系统操作的客户端实例对象
FileSystem fs = FileSystem.get(context.getConfiguration()); Path enhancePath = new Path("F:/temp/en/log.dat");
Path tocrawlPath = new Path("F:/temp/crw/url.dat");
//流式创建文件
FSDataOutputStream enhancedOs = fs.create(enhancePath);
FSDataOutputStream tocrawlOs = fs.create(tocrawlPath); return new EnhanceRecordWriter(enhancedOs, tocrawlOs);
} /**
* 构造一个自己的recordwriter
*/
static class EnhanceRecordWriter extends RecordWriter<Text, NullWritable> { FSDataOutputStream enhancedOs = null;
FSDataOutputStream tocrawlOs = null; public EnhanceRecordWriter(FSDataOutputStream enhancedOs, FSDataOutputStream tocrawlOs) {
super();
this.enhancedOs = enhancedOs;
this.tocrawlOs = tocrawlOs;
}
//实现抽象方法write
@Override
public void write(Text key, NullWritable value) throws IOException, InterruptedException {
String result = key.toString();
// 如果要写出的数据是待爬的url,则写入待爬清单文件 /logenhance/tocrawl/url.dat
if (result.contains("tocrawl")) {
tocrawlOs.write(result.getBytes());
} else {
// 如果要写出的数据是增强日志,则写入增强日志文件 /logenhance/enhancedlog/log.dat
enhancedOs.write(result.getBytes());
}
}
//实现抽象方法close
@Override
public void close(TaskAttemptContext context) throws IOException, InterruptedException {
if (tocrawlOs != null) {
tocrawlOs.close();
}
if (enhancedOs != null) {
enhancedOs.close();
}
}
}
}

3.开发mapreduce处理流程:

  这个程序是对每个小时不断产生的用户上网记录日志进行增强(将日志中的url所指向的网页内容分析结果信息追加到每一行

原始日志后面

  maptask在初始化时会先调用setup方法一次 利用这个机制,将外部的知识库加载到maptask执行的机器内存中

package cn.bigdata.hdfs.LogEnhance;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class LogEnhance { static class LogEnhanceMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
Map<String, String> ruleMap = new HashMap<String, String>();
Text k = new Text();
NullWritable v = NullWritable.get(); // 从数据库中加载规则信息倒ruleMap中
@Override
protected void setup(Context context) throws IOException, InterruptedException { try {
DBLoader.dbLoader(ruleMap);
} catch (Exception e) {
e.printStackTrace();
}
} @Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 获取一个计数器用来记录不合法的日志行数, 组名, 计数器名称
Counter counter = context.getCounter("malformed", "malformedline");
String line = value.toString();
String[] fields = StringUtils.split(line, "\t");
try {
String url = fields[26];
String content_tag = ruleMap.get(url);
// 判断内容标签是否为空,如果为空,则只输出url到待爬清单;如果有值,则输出到增强日志
if (content_tag == null) {
k.set(url + "\t" + "tocrawl" + "\n");
context.write(k, v);
} else {
k.set(line + "\t" + content_tag + "\n");
context.write(k, v);
}
} catch (Exception exception) {
counter.increment(1);
}
}
} public static void main(String[] args) throws Exception { Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
job.setJarByClass(LogEnhance.class);
job.setMapperClass(LogEnhanceMapper.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class); // 要控制不同的内容写往不同的目标路径,可以采用自定义outputformat的方法
job.setOutputFormatClass(LogEnhanceOutputFormat.class);
//本地原始日志文件存放目录
FileInputFormat.setInputPaths(job, new Path("F:/webloginput/"));
// 尽管我们用的是自定义outputformat,但是它是继承制fileoutputformat
// 在fileoutputformat中,必须输出一个_success文件,所以在此还需要设置输出path
FileOutputFormat.setOutputPath(job, new Path("F:/weblogoutput/")); // 不需要reducer
job.setNumReduceTasks(0); job.waitForCompletion(true);
System.exit(0);
}
}

总结:

  1.其中在mapreduce程序中用到了计数器;获取一个计数器用来记录不合法的日志行数, 组名, 计数器名称

  2.拷贝mysql的驱动包到工程的lib目录下,这里使用本地运行模式;https://pan.baidu.com/s/1ldzQ0i5qdvvJ3Yw08LvF5Q

  3.maptask或者reducetask在最终输出时,先调用OutputFormat的getRecordWriter方法拿到一个RecordWriter,然后再调用

RecordWriter的write(k,v)方法将数据写出

  4.在setup方法中完成知识库的加载,写入到Map中

  5.Map端在Context,write时,如果后面没有Reduce,将没有整个的shuffe过程,将直接调用outPutFormat进行输出,进来什

么顺序,则出去什么顺序(总之:没有reduce就没有shuffle)

  

Hadoop_27_MapReduce_运营商原始日志增强(自定义OutputFormat)的更多相关文章

  1. 运营商手机视频流量包业务日志ETL及统计分析

    自己做过的项目在这里做一个记录,否则就感觉不是自己的了.一是因为过去时间已经很长了,二是因为当时做得有点粗糙,最后还不了了之了. 话不多说,先大致介绍一下项目背景.以前各大手机视频 App 一般都有运 ...

  2. Hadoop案例(五)过滤日志及自定义日志输出路径(自定义OutputFormat)

    过滤日志及自定义日志输出路径(自定义OutputFormat) 1.需求分析 过滤输入的log日志中是否包含xyg (1)包含xyg的网站输出到e:/xyg.log (2)不包含xyg的网站输出到e: ...

  3. 100.64.0.0/10运营商级(Carrier-grade)NAT保留IP地址

    在一次跟踪路由的网络操作时发现自己路由器下一跳路由节点的IP地址比较奇怪,是100.64.0.1.好奇促使我查询了这个IP地址的归属,结果是保留地址,到这里觉得比较奇怪了,按照常理以IPv4为例保留的 ...

  4. Unity获取安卓手机运营商,电量,wifi信号强度,本地Toast,获取已安装apk,调用第三方应用,强制自动重启本应用

    一个完整的游戏项目上线需要不断的完善优化,但是到了后期的开发不再仅仅是游戏了,它的复杂度远远大于纯粹的应用开发.首先必须要考虑的就是集成第三方SDK,支付这块渠道商已经帮你我们做好了,只需要按照文档对 ...

  5. CSP -- 运营商内容劫持(广告)的终结者

    缘由 我们公司最近手机端H5 经常受到商户和用户的投诉,说有广告并且导致不能正常进行操作,我们商户自己当然不会加广告了,但是商户和用户可不管这些了,就认为是我们的问题 探索发现根本 目前我们用的很多浏 ...

  6. 你们以为运营商只是HTTP插点广告而已么?

    国内某邮件服务商,近期在某南方地区有大量客户反应登录时出错和异常,于是工作人员进行了一下跟进,发现如下: 首先,邮件服务商登陆页面为普通HTTP协议发送,提交时通过JS进行RSA加密(没错,JS的RS ...

  7. 电信运营商 IT 系统介绍

    业务支撑系统 BSS: Business support system  运营支撑系统 OSS: Operation support system  管理支撑系统 MSS: Management Su ...

  8. 运营商DNS系统安全解决方案

    DNS系统面临的主要风险 目前,DNS面临的安全问题主要可以分为三类:DNS欺骗攻击.拒绝服务攻击.系统漏洞,下文将分别进行介绍.  DNS欺骗攻击 当一个DNS服务器遭到欺骗攻击,使用了来自一个恶 ...

  9. 运营商 WLAN

    运营商 WLAN 运营商 WLAN 是 Android 9 中引入的一项功能,该功能可让设备自动连接到运营商实现的 WLAN 网络.在高度拥塞或信号覆盖范围较小的区域(如体育场或地铁站),运营商 WL ...

随机推荐

  1. C#使用CUDA

    随着信息处理的爆炸增长,传统使用CPU计算已经无法满足计算作业增长的需求,GPU的出现为批量作业提供了新的契机.GPU计算拥有很类库,比如CUDA.OpenCL等,但是可以发现CUDA是其中相对比较成 ...

  2. CentOS修改主机名称

    centos6 或者centos7修改主机名称的方式 centos6 修改主机名 [root@centos6 ~]$ hostname # 查看当前的hostnmae centos6.com [roo ...

  3. flask上下管理文相关 - 总结

    flask上下管理文相关 - 总结 flask上下文管理机制 当用户请求到来之后,flask内部会创建两个对象: ctx = ReqeustContext(),内部封装request/sesion a ...

  4. JavaScript 短路值

    了解表达式中的短路值. 逻辑运算从左到右.逻辑或运算,当左边的条件成立时,后面的条件将不再参与运算.因此在逻辑或运算中,尽量将条件结果为true的放第一位.而在逻辑与运算中,尽量将条件结果为false ...

  5. 2018南京icpc-J-Prime Game (欧拉筛+唯一分解定理)

    题意:给定n个数ai(n<=1e6,ai<=1e6),定义,并且fac(l,r)为mul(l,r)的不同质因数的个数,求 思路:可以先用欧拉筛求出1e6以内的所有质数,然后对所有ai判断, ...

  6. 【Python】【demo实验35】【基础实验】【排序】【选择法排序】

    原题: 使用选择法对10个数字排序: 即取10个数中最小的放在第一个位置,再取剩下9个中最小的放在第二个位置... 我的源码: #!/usr/bin/python # encoding=utf-8 # ...

  7. TP5.1框架中的模型关联

    一对一关联 hasOne('关联模型','外键','主键'); 关联模型(必须):关联的模型名或者类名 外键:默认的外键规则是当前模型名(不含命名空间,下同)+_id ,例如user_id 主键:当前 ...

  8. EXCEL 查找某个字符在字符串中最后一次出现的位置

    在EXCEL文档里想从很长的文件路径中取得文件名,[数据]→[分列]是个不错的选择,但用函数会显得更高大上一些. 首先,需要获取最后一个"\"所在的位置. 方法1: FIND(&q ...

  9. 关于日志slf4j+logback&logback.xml配置

    1.maven依赖 <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <!-- <dependen ...

  10. 【Trie】Secret Message 秘密信息

    [题目链接]: https://loj.ac/problem/10054 [题意] 我认为这个题目最难的是题意: 其实分了两种情况: 1.如果当前文本串匹配不完,那么答案的是:匹配过程中遇到的模式串结 ...