使用Hadoop统计日志数据
发表于:2025-02-22 作者:千家信息网编辑
千家信息网最后更新 2025年02月22日,用户行为日志概述用户行为日志:用户每次访问网站时所有的行为数据访问、浏览、搜索、点击...用户行为轨迹、流量日志(用户行为日志的其他名称)为什么要记录用户访问行为日志:进行网站页面的访问量的统计分析网
千家信息网最后更新 2025年02月22日使用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安全错误
数据库的锁怎样保障安全
软件开发手册编写
青年干部网络安全
服务器下载文件耗内存吗
校园网络安全方面事例
数据库开发工作经验
小学网络安全知识试题
oracle 数据库引擎
关系数据库差运算
天津进口软件开发经历
服务器能接到非管理交换机吗
git 镜像服务器
文化安全 网络安全
网络安全策划 论文
怎样在万方数据库下载资料
锡山区工程软件开发平均价格
空间数据库实验二答案
信息网络安全意识培养简报
nivacat导出数据库
数学专业适合干软件开发吗
互联网科技企业文化墙
狼盟网络技术交流论坛
ecm服务器
启明网络安全审计
由于 web服务器上
网络安全ccna考试题
奉贤区服务软件开发统计
智能售酒机软件开发
腾讯会议在哪改代理服务器设置
软件数据库在哪里查看
mq服务器的应用