使用Hadoop统计日志数据
发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,用户行为日志概述用户行为日志:用户每次访问网站时所有的行为数据访问、浏览、搜索、点击...用户行为轨迹、流量日志(用户行为日志的其他名称)为什么要记录用户访问行为日志:进行网站页面的访问量的统计分析网
千家信息网最后更新 2024年11月20日使用Hadoop统计日志数据
用户行为日志概述
用户行为日志:
- 用户每次访问网站时所有的行为数据
- 访问、浏览、搜索、点击...
- 用户行为轨迹、流量日志(用户行为日志的其他名称)
为什么要记录用户访问行为日志:
- 进行网站页面的访问量的统计
- 分析网站的黏性
- 训练推荐系统
用户行为日志生成渠道:
- web服务器记录的web访问日志
- ajax记录的访问日志以及其他相关的日志
用户行为日志大致内容:
- 访问时间
- 访问者所使用的客户端(UserAgent)
- 访问者的IP地址
- 访问者账号
- 某个页面的停留时间
- 访问的时间与地点
- 跳转的链接地址(referer)
- 访问信息,例如:session_id
- 模块AppID
用户行为日志分析的意义:
- 网站的眼睛,能够看到用户的主要来源、喜好网站上的哪些内容,以及用户的忠诚度等
- 网站的神经,通过分析用户行为日志,我们能对网站的布局、功能进一步的优化,以提高用户的体验等
- 网站的大脑,通过分析结果,进行推广预算的划分,以及重点优化用户群体的倾向点等
离线数据处理架构
离线数据处理流程:
- 数据采集
- 例如可以使用Flume进行数据的采集:将web日志写入到HDFS
- 数据清洗
- 可以使用Spark、Hive、MapReduce等框架进行数据的清洗,清洗完之后的数据可以存放在HDFS或者Hive、Spark SQL里
- 数据处理
- 按照我们的需求进行相应业务的统计和分析
- 数据处理结果入库
- 结果可以存放到RDBMS、NoSQL数据库
- 数据的可视化展示
- 通过图形化展示的方式展现出来:饼图、柱状图、地图、折线图等等
- 工具:ECharts、HUE、Zeppelin
流程示意图:
项目需求
需求:
- 统计网站访问日志中每个浏览器的访问次数
日志片段如下:
183.162.52.7 - - [10/Nov/2016:00:01:02 +0800] "POST /api3/getadv HTTP/1.1" 200 813 "www.xxx.com" "-" cid=0×tamp=1478707261865&uid=2871142&marking=androidbanner&secrect=a6e8e14701ffe9f6063934780d9e2e6d&token=f51e97d1cb1a9caac669ea8acc162b96 "mukewang/5.0.0 (Android 5.1.1; Xiaomi Redmi 3 Build/LMY47V),Network 2G/3G" "-" 10.100.134.244:80 200 0.027 0.02710.100.0.1 - - [10/Nov/2016:00:01:02 +0800] "HEAD / HTTP/1.1" 301 0 "117.121.101.40" "-" - "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh3/1.4.2" "-" - - - 0.000
功能实现之UserAgent解析类测试
首先我们需要根据日志信息抽取出浏览器信息,针对不同的浏览器进行统计操作。虽然可以自己实现这个功能,但是懒得再造轮子了,所以我在GitHub找到了一个小工具可以完成这个功能,GitHub地址如下:
https://github.com/LeeKemp/UserAgentParser
通过git clone或者浏览器下载到本地后,使用命令行进入到其主目录下,然后通过maven命令对其进行打包并安装到本地仓库里:
$ mvn clean package -DskipTest$ mvn clean install -DskipTest
安装完成后,在工程中添加依赖以及插件:
cloudera https://repository.cloudera.com/artifactory/cloudera-repos/ true false UTF-8 2.6.0-cdh6.7.0 org.apache.hadoop hadoop-client ${hadoop.version} provided com.kumkee UserAgentParser 0.0.1 junit junit 4.10 test maven-assembly-plugin jar-with-dependencies
然后我们编写一个测试用例来测试一下这个解析类,因为之前并没有使用过这个工具,所以对于一个未使用过的工具,要养成在工程中使用之前对其进行测试的好习惯:
package org.zero01.project;import com.kumkee.userAgent.UserAgent;import com.kumkee.userAgent.UserAgentParser;/** * @program: hadoop-train * @description: UserAgent解析测试类 * @author: 01 * @create: 2018-04-01 22:43 **/public class UserAgentTest { public static void main(String[] args) { String source = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36"; UserAgentParser userAgentParser = new UserAgentParser(); UserAgent agent = userAgentParser.parse(source); String browser = agent.getBrowser(); String engine = agent.getEngine(); String engineVersion = agent.getEngineVersion(); String os = agent.getOs(); String platform = agent.getPlatform(); boolean isMobile = agent.isMobile(); System.out.println("浏览器:" + browser); System.out.println("引擎:" + engine); System.out.println("引擎版本:" + engineVersion); System.out.println("操作系统:" + os); System.out.println("平台:" + platform); System.out.println("是否是移动设备:" + isMobile); }}
控制台输出结果如下:
浏览器:Chrome引擎:Webkit引擎版本:537.36操作系统:Windows 7平台:Windows是否是移动设备:false
从打印结果可以看到,UserAgent的相关信息都正常获取到了,我们就可以在工程中进行使用这个工具了。
使用MapReduce完成需求统计
创建一个类,编写代码如下:
package org.zero01.hadoop.project;import com.kumkee.userAgent.UserAgent;import com.kumkee.userAgent.UserAgentParser;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;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.Mapper;import org.apache.hadoop.mapreduce.Reducer;import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * @program: hadoop-train * @description: 使用MapReduce来完成统计浏览器的访问次数 * @author: 01 * @create: 2018-04-02 14:20 **/public class LogApp { /** * Map: 读取输入的文件内容 */ public static class MyMapper extends Mapper { LongWritable one = new LongWritable(1); private UserAgentParser userAgentParser; protected void setup(Context context) throws IOException, InterruptedException { userAgentParser = new UserAgentParser(); } protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 接收到的每一行日志信息 String line = value.toString(); String source = line.substring(getCharacterPosition(line, "\"", 7) + 1); UserAgent agent = userAgentParser.parse(source); String browser = agent.getBrowser(); // 通过上下文把map的处理结果输出 context.write(new Text(browser), one); } protected void cleanup(Context context) throws IOException, InterruptedException { userAgentParser = null; } } /** * Reduce: 归并操作 */ public static class MyReducer extends Reducer { protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException { long sum = 0; for (LongWritable value : values) { // 求key出现的次数总和 sum += value.get(); } // 将最终的统计结果输出 context.write(key, new LongWritable(sum)); } } /** * 获取指定字符串中指定标识的字符串出现的索引位置 * * @param value * @param operator * @param index * @return */ private static int getCharacterPosition(String value, String operator, int index) { Matcher slashMatcher = Pattern.compile(operator).matcher(value); int mIdex = 0; while (slashMatcher.find()) { mIdex++; if (mIdex == index) { break; } } return slashMatcher.start(); } /** * 定义Driver:封装了MapReduce作业的所有信息 */ public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration configuration = new Configuration(); // 准备清理已存在的输出目录 Path outputPath = new Path(args[1]); FileSystem fileSystem = FileSystem.get(configuration); if (fileSystem.exists(outputPath)) { fileSystem.delete(outputPath, true); System.out.println("output file exists, but is has deleted"); } // 创建Job,通过参数设置Job的名称 Job job = Job.getInstance(configuration, "LogApp"); // 设置Job的处理类 job.setJarByClass(LogApp.class); // 设置作业处理的输入路径 FileInputFormat.setInputPaths(job, new Path(args[0])); // 设置map相关参数 job.setMapperClass(LogApp.MyMapper.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(LongWritable.class); // 设置reduce相关参数 job.setReducerClass(LogApp.MyReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(LongWritable.class); // 设置作业处理完成后的输出路径 FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); }}
在工程目录下打开控制台,输入如下命令进行打包:
mvn assembly:assembly
打包成功:
将这个jar包上传到服务器上:
[root@localhost ~]# rz # 使用的是Xshell工具,所以直接使用rz命令即可上传文件[root@localhost ~]# ls |grep hadoop-train-1.0-jar-with-dependencies.jar # 查看是否上传成功hadoop-train-1.0-jar-with-dependencies.jar[root@localhost ~]#
把事先准备好的日志文件上传到HDFS文件系统中:
[root@localhost ~]# hdfs dfs -put ./10000_access.log /[root@localhost ~]# hdfs dfs -ls /10000_access.log-rw-r--r-- 1 root supergroup 2769741 2018-04-02 22:33 /10000_access.log[root@localhost ~]#
执行如下命令
[root@localhost ~]# hadoop jar ./hadoop-train-1.0-jar-with-dependencies.jar org.zero01.hadoop.project.LogApp /10000_access.log /browserout
执行成功:
查看处理结果:
[root@localhost ~]# hdfs dfs -ls /browseroutFound 2 items-rw-r--r-- 1 root supergroup 0 2018-04-02 22:42 /browserout/_SUCCESS-rw-r--r-- 1 root supergroup 56 2018-04-02 22:42 /browserout/part-r-00000[root@localhost ~]# hdfs dfs -text /browserout/part-r-00000Chrome 2775Firefox 327MSIE 78Safari 115Unknown 6705[root@localhost ~]#
日志
用户
数据
行为
网站
处理
结果
浏览
统计
浏览器
信息
工具
命令
分析
测试
输出
功能
工程
引擎
数据处理
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
车载大屏连手机热点服务器错误
网络安全面试问什么问题
smtp服务器主机名
微博的网络技术
sql 镜像数据库
微信小程序添加数据库
数据库销售定义
航天长屏做网络安全的公司
软件开发公司结束语怎么写
合大发上海网络技术有限公司
服务器常见安全问题解决方案
网络安全会议通知 市政府
青山联想服务器供应商
qt打开数据库
怎么新建数据库和模式
网络安全保卫机制
安微芯购互联网科技有限公司
幼儿手抄报网络安全
数据库数据纵向变横向
企业网络安全需求
相片上传云服务器怎么关
1700亿网络安全生态
校园网络安全情况工作机制
gdb数据如何导入到数据库
黑客服务器宣传
常规软件开发资费
校外下载学校数据库的文献
济源职业技术学院网络技术
计算机网络技术最好的证书
it互联网云科技ppt模板