离线数仓 (三) --------- 用户行为数据生成模块


一、目标数据

我们要收集和分析的数据主要包括页面数据、事件数据、曝光数据、启动数据和错误数据

1. 页面

页面数据主要记录一个页面的用户访问情况,包括访问时间、停留时间、页面路径等信息。

在这里插入图片描述

字段名称字段描述
page_id页面 id :home(“首页”),category(“分类页”),discovery(“发现页”),top_n(“热门排行”),favor(“收藏页”),search(“搜索页”),good_list(“商品列表页”),good_detail(“商品详情”),good_spec(“商品规格”),comment(“评价”),comment_done(“评价完成”),comment_list(“评价列表”),cart(“购物车”),trade(“下单结算”),payment(“支付页面”),payment_done(“支付完成”),orders_all(“全部订单”),orders_unpaid(“订单待支付”),,orders_undelivered(“订单待发货”),orders_unreceipted(“订单待收货”),orders_wait_comment(“订单待评价”),mine(“我的”),activity(“活动”),login(“登录”),register(“注册”)
last_page_id上页id
page_item_type页面对象类型: sku_id(“商品skuId”),keyword(“搜索关键词”),sku_ids(“多个商品skuId”),activity_id(“活动id”),coupon_id(“购物券id”);
page_item页面对象id
sourceType页面来源类型: promotion(“商品推广”),recommend(“算法推荐商品”),query(“查询结果商品”), activity(“促销活动”)
during_time停留时间(毫秒)
ts跳入时间

2. 事件

事件数据主要记录应用内一个具体操作行为,包括操作类型、操作对象、操作对象描述等信息。

在这里插入图片描述

字段名称字段描述
action_id动作id: favor_add(“添加收藏”),favor_canel(“取消收藏”),cart_add(“添加购物车”),cart_remove(“删除购物车”),cart_add_num(“增加购物车商品数量”),cart_minus_num(“减少购物车商品数量”),trade_add_address(“增加收货地址”),get_coupon(“领取优惠券”),注:对于下单、支付等业务数据,可从业务数据库获取。
item_type动作目标类型: sku_id(“商品”),coupon_id(“购物券”)
item动作目标id
ts动作时间

3. 曝光

曝光数据主要记录页面所曝光的内容,包括曝光对象,曝光类型等信息。

在这里插入图片描述

字段名称字段描述
displayType曝光类型 :promotion(“商品推广”),recommend(“算法推荐商品”),query(“查询结果商品”),activity(“促销活动”);
item_type曝光对象类型 : sku_id(“商品skuId”),activity_id(“活动id”)、
item曝光对象id
order曝光顺序

4. 启动

启动数据记录应用的启动信息。

在这里插入图片描述

字段名称字段描述
entry启动入口 : icon(“图标”),notification(“通知”),install(“安装后启动”);
loading_time启动加载时间
open_ad_id开屏广告id
open_ad_ms广告播放时间
open_ad_skip_ms用户跳过广告时间
ts启动时间

5. 错误

错误数据记录应用使用过程中的错误信息,包括错误编号及错误信息。

字段名称字段描述
error_code错误码
msg错误信息

二、数据埋点

1. 主流埋点方式 (了解)

目前主流的埋点方式,有代码埋点 (前端/后端)、可视化埋点、全埋点三种。

代码埋点是通过调用埋点SDK函数,在需要埋点的业务逻辑功能位置调用接口,上报埋点数据。例如,我们对页面中的某个按钮埋点后,当这个按钮被点击时,可以在这个按钮对应的 OnClick 函数里面调用SDK 提供的数据发送接口,来发送数据。

可视化埋点只需要研发人员集成采集 SDK,不需要写埋点代码,业务人员就可以通过访问分析平台的 “圈选” 功能,来 “圈” 出需要对用户行为进行捕捉的控件,并对该事件进行命名。圈选完毕后,这些配置会同步到各个用户的终端上,由采集 SDK 按照圈选的配置自动进行用户行为数据的采集和发送。

全埋点是通过在产品中嵌入SDK,前端自动采集页面上的全部用户行为事件,上报埋点数据,相当于做了一个统一的埋点。然后再通过界面配置哪些数据需要在系统里面进行分析。

2. 埋点数据上报时机

埋点数据上报时机包括两种方式。

方式一,在离开该页面时,上传在这个页面产生的所有数据(页面、事件、曝光、错误等)。优点,批处理,减少了服务器接收数据压力。缺点,不是特别及时。

方式二,每个事件、动作、错误等,产生后,立即发送。优点,响应及时。缺点,对服务器接收数据压力比较大。

本次项目采用方式一埋点。

3. 埋点数据日志结构

我们的日志结构大致可分为两类,一是普通页面埋点日志,二是启动日志。

普通页面日志结构如下,每条日志包含了,当前页面的页面信息,所有事件 (动作) 、所有曝光信息以及错误信息。除此之外,还包含了一系列公共信息,包括设备信息,地理位置,应用信息等,即下边的common字段。

A、普通页面埋点日志格式

{
  "common": {                  -- 公共信息
    "ar": "230000",              -- 地区编码
    "ba": "iPhone",              -- 手机品牌
    "ch": "Appstore",            -- 渠道
    "is_new": "1",--是否首日使用,首次使用的当日,该字段值为1,过了24:00,该字段置为0"md": "iPhone 8",            -- 手机型号
    "mid": "YXfhjAYH6As2z9Iq", -- 设备id
    "os": "iOS 13.2.9",          -- 操作系统
    "uid": "485",                 -- 会员id
    "vc": "v2.1.134"             -- app版本号
  },
 "actions": [                     --动作(事件)  
    {
      "action_id": "favor_add",   --动作id
      "item": "3",                   --目标id
      "item_type": "sku_id",       --目标类型
      "ts": 1585744376605           --动作时间戳
    }
  ],
  "displays": [
    {
      "displayType": "query",        -- 曝光类型
      "item": "3",                     -- 曝光对象id
      "item_type": "sku_id",         -- 曝光对象类型
      "order": 1,                      --出现顺序
      "pos_id": 2                      --曝光位置
    },
    {
      "displayType": "promotion",
      "item": "6",
      "item_type": "sku_id",
      "order": 2, 
      "pos_id": 1
    },
    {
      "displayType": "promotion",
      "item": "9",
      "item_type": "sku_id",
      "order": 3, 
      "pos_id": 3
    },
    {
      "displayType": "recommend",
      "item": "6",
      "item_type": "sku_id",
      "order": 4, 
      "pos_id": 2
    },
    {
      "displayType": "query ",
      "item": "6",
      "item_type": "sku_id",
      "order": 5, 
      "pos_id": 1
    }
  ],
  "page": {                       -- 页面信息
    "during_time": 7648,          -- 持续时间毫秒
    "item": "3",                  -- 目标id
    "item_type": "sku_id",        -- 目标类型
    "last_page_id": "login",      -- 上页类型
    "page_id": "good_detail",     -- 页面ID
    "sourceType": "promotion"     -- 来源类型
  },
  "err":{                         -- 错误
	"error_code": "1234",         -- 错误码
    "msg": "***********"          -- 错误信息
  },
  "ts": 1585744374423             -- 跳入时间戳
}

B、启动日志格式

启动日志结构相对简单,主要包含公共信息,启动信息和错误信息。

{
  "common": {
    "ar": "370000",
    "ba": "Honor",
    "ch": "wandoujia",
    "is_new": "1",
    "md": "Honor 20s",
    "mid": "eQF5boERMJFOujcp",
    "os": "Android 11.0",
    "uid": "76",
    "vc": "v2.1.134"
  },
  "start": {   
    "entry": "icon",           -- icon 手机图标  notice 通知  install 安装后启动
    "loading_time": 18803,     -- 启动加载时间
    "open_ad_id": 7,           -- 广告页ID
    "open_ad_ms": 3449,        -- 广告总共播放时间
    "open_ad_skip_ms": 1989    -- 用户跳过广告时点
  },
  "err":{                      -- 错误
	"error_code": "1234",      -- 错误码
    "msg": "***********"       -- 错误信息
  },
  "ts": 1585744304000
}

三、服务器和 JDK 准备

1. 服务器

在此以虚拟机为例,配置三台虚拟器作为 hadoop 所需服务器集群。。。,详见之前写过的 Hadoop (三) --------- Hadoop 运行环境搭建 (虚拟机) 这篇文章

2. 编写集群分发脚本 xsync

A、xsync集群分发脚本

  • 需求:循环复制文件到所有节点的相同目录下

  • 需求分析
    ① rsync 命令原始拷贝:rsync -av /opt/module root@node103:/opt/
    ② 期望脚本:xsync要同步的文件名称
    ③ 说明:在 /home/fancy/bin 这个目录下存放的脚本,/home/fancy 用户可以在系统任何地方直接执行。

B、脚本实现

① 在用户的家目录 /home/fancy 下创建 bin 文件夹

[fancy@hadoop102 ~]$ mkdir bin

② 在 /home/fancy/bin 目录下创建 xsync 文件,以便全局调用

[fancy@node101  ~]$ cd /home/fancy/bin
[fancy@node102  ~]$ vim xsync

在该文件中编写如下代码

#!/bin/bash
#1. 判断参数个数
if [ $# -lt 1 ]
then
  echo Not Enough Arguement!
  exit;
fi
#2. 遍历集群所有机器
for host in node101 node102 node103
do
  echo ====================  $host  ====================
  #3. 遍历所有目录,挨个发送
  for file in $@
  do
    #4 判断文件是否存在
    if [ -e $file ]
    then
      #5. 获取父目录
      pdir=$(cd -P $(dirname $file); pwd)
      #6. 获取当前文件的名称
      fname=$(basename $file)
      ssh $host "mkdir -p $pdir"
      rsync -av $pdir/$fname $host:$pdir
    else
      echo $file does not exists!
    fi
  done
done

③修改脚本xsync具有执行权限

[fancy@node101 bin]$ chmod +x xsync

④测试脚本

[fancy@node101 bin]$ xsync xsync

3. SSH 无密登录配置

说明:这里面只配置了 node101、node102 到其他主机的无密登录。因为 node101 未外配置的是 NameNode,node102 配置的是 ResourceManager,都要求对其他节点无密访问。

A、node101 上生成公钥和私钥

[fancy@node101 .ssh]$ ssh-keygen -t rsa

然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)

B、将 node101 公钥拷贝到要免密登录的目标机器上

[fancy@node101  .ssh]$ ssh-copy-id node101
[fancy@node101  .ssh]$ ssh-copy-id node102
[fancy@node101  .ssh]$ ssh-copy-id node103

C、node102 上生成公钥和私钥

[fancy@node102 .ssh]$ ssh-keygen -t rsa

然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)

D、将 node102 公钥拷贝到要免密登录的目标机器上

[fancy@node102 .ssh]$ ssh-copy-id node101	
[fancy@node102 .ssh]$ ssh-copy-id node102
[fancy@node102 .ssh]$ ssh-copy-id node103

4. JDK准备

A、卸载现有JDK(3台节点)

[fancy@node101 opt]# sudo rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps

[fancy@node102  opt]# sudo rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps

[fancy@node103  opt]# sudo rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps
  • rpm -qa :表示查询所有已经安装的软件包
  • grep -i :表示过滤时不区分大小写
  • xargs -n1 :表示一次获取上次执行结果的一个值
  • rpm -e --nodeps :表示卸载软件

B、用 XShell 工具将 JDK 导入到 node101 的 /opt/software 文件夹下面

在Linux系统下的opt目录中查看软件包是否导入成功

[fancy@node101 software]# ls /opt/software/

看到如下结果:

jdk-8u212-linux-x64.tar.gz

C、解压JDK到/opt/module目录下

[fancy@node101 software]# tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/module/

D、配置JDK环境变量

新建 /etc/profile.d/my_env.sh 文件

[fancy@node101 module]# sudo vim /etc/profile.d/my_env.sh

添加如下内容,然后保存(:wq)退出

#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_212
export PATH=$PATH:$JAVA_HOME/bin

让环境变量生效

[fancy@hadoop102 software]$ source /etc/profile.d/my_env.sh

E、测试JDK是否安装成功

[fancy@node101 module]# java -version

如果能看到以下结果,则 Java 正常安装

java version "1.8.0_212"

F、分发JDK

[fancy@node101 module]$ xsync /opt/module/jdk1.8.0_212/

G、分发环境变量配置文件

[fancy@node101 module]$ sudo /home/fancy/bin/xsync /etc/profile.d/my_env.sh

H、分别在 node102、node103 上执行 source

[fancy@node102 module]$ source /etc/profile.d/my_env.sh
[fancy@node103 module]$ source /etc/profile.d/my_env.sh

5. 环境变量配置说明

Linux 的环境变量可在多个文件中配置,如 /etc/profile/etc/profile.d/*.sh~/.bashrc~/.bash_profile 等,下面说明上述几个文件之间的关系和区别。

bash的运行模式可分为 login shell 和 non-login shell。

例如,我们通过终端,输入用户名、密码,登录系统之后,得到就是一个 login shell。而当我们执行以下命令ssh node102 command,在 node102 执行command的就是一个non-login shell。

在这里插入图片描述
这两种 shell 的主要区别在于,它们启动时会加载不同的配置文件,login shell 启动时会加载/etc/profile~/.bash_profile~/.bashrc。non-login shell启动时会加载 ~/.bashrc

而在加载 ~/.bashrc(实际是 ~/.bashrc 中加载的 /etc/bashrc)或 /etc/profile 时,都会执行如下代码片段

在这里插入图片描述

因此不管是 login shell 还是 non-login shell,启动时都会加载 /etc/profile.d/*.sh 中的环境变量。

四、模拟数据

1. 使用说明

A、将 application.yml、gmall2020-mock-log-2021-01-22.jar、path.json、logback.xml 上传到 node101 的 /opt/module/applog 目录下

创建 applog 路径

[fancy@hadoop102 module]$ mkdir /opt/module/applog

上传文件 application.yml 到 /opt/module/applog 目录

B、配置文件

application.yml文件:

可以根据需求生成对应日期的用户行为日志。

[fancy@hadoop102 applog]$ vim application.yml

修改如下内容:

# 外部配置打开
# 外部配置打开
logging.config: "./logback.xml"
#业务日期  注意:并不是Linux系统生成日志的日期,而是生成数据中的时间
mock.date: "2020-06-14"

#模拟数据发送模式
#mock.type: "http"
#mock.type: "kafka"
mock.type: "log"

#http模式下,发送的地址
mock.url: "http://hdp1/applog"

#kafka模式下,发送的地址
mock:
  kafka-server: "hdp1:9092,hdp2:9092,hdp3:9092"
  kafka-topic: "ODS_BASE_LOG"

#启动次数
mock.startup.count: 200
#设备最大值
mock.max.mid: 500000
#会员最大值
mock.max.uid: 100
#商品最大值
mock.max.sku-id: 35
#页面平均访问时间
mock.page.during-time-ms: 20000
#错误概率 百分比
mock.error.rate: 3
#每条日志发送延迟 ms
mock.log.sleep: 10
#商品详情来源  用户查询,商品推广,智能推荐, 促销活动
mock.detail.source-type-rate: "40:25:15:20"
#领取购物券概率
mock.if_get_coupon_rate: 75
#购物券最大id
mock.max.coupon-id: 3
#搜索关键词  
mock.search.keyword: "图书,小米,iphone11,电视,口红,ps5,苹果手机,小米盒子"

path.json,该文件用来配置访问路径:

根据需求,可以灵活配置用户点击路径。

[
	{"path":["home","good_list","good_detail","cart","trade","payment"],"rate":20 },
	{"path":["home","search","good_list","good_detail","login","good_detail","cart","trade","payment"],"rate":40 },
	{"path":["home","mine","orders_unpaid","trade","payment"],"rate":10 },
	{"path":["home","mine","orders_unpaid","good_detail","good_spec","comment","trade","payment"],"rate":5 },
	{"path":["home","mine","orders_unpaid","good_detail","good_spec","comment","home"],"rate":5 },
	{"path":["home","good_detail"],"rate":10 },
	{"path":["home"  ],"rate":10 }
]

logback配置文件:

可配置日志生成路径,修改内容如下

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_HOME" value="/opt/module/applog/log" />
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>

    <appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>

    <!-- 将某一个包下日志单独打印日志 -->
    <logger name="com.atgugu.gmall2020.mock.log.util.LogUtil"
            level="INFO" additivity="false">
        <appender-ref ref="rollingFile" />
        <appender-ref ref="console" />
    </logger>

    <root level="error"  >
        <appender-ref ref="console" />
    </root>
</configuration>

C、生成日志

进入到 /opt/module/applog 路径,执行以下命令

[fancy@node101 applog]$ java -jar gmall2020-mock-log-2021-01-22.jar

/opt/module/applog/log 目录下查看生成日志

[fancy@node101 log]$ ll

2. 集群日志生成脚本

在 node101 的 /home/fancy 目录下创建 bin 目录,这样脚本可以在服务器的任何目录执行。

[fancy@node101 ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/fancy/.local/bin:/home/fancy/bin

A、在 /home/fancy/bin 目录下创建脚本lg.sh

[fancy@node101 bin]$ vim lg.sh

B、在脚本中编写如下内容

#!/bin/bash
for i in node101 node102; do
    echo "========== $i =========="
    ssh $i "cd /opt/module/applog/; java -jar gmall2020-mock-log-2021-01-22.jar >/dev/null 2>&1 &"
done 

注:
/opt/module/applog/ 为 jar 包及配置文件所在路径
/dev/null 代表 Linux 的空设备文件,所有往这个文件里面写入的内容都会丢失,俗称“黑洞”。

  • 标准输入0:从键盘获得输入 /proc/self/fd/0
  • 标准输出1:输出到屏幕(即控制台) /proc/self/fd/1
  • 错误输出2:输出到屏幕(即控制台)/proc/self/fd/2

C、修改脚本执行权限

[fancy@hadoop102 bin]$ chmod u+x lg.sh

D、将 jar 包及配置文件上传至 node101 的 /opt/module/applog/ 路径

E、启动脚本

[fancy@hadoop102 module]$ lg.sh 

F、分别在node101、node102的/opt/module/applog/log目录上查看生成的数据

[fancy@node101 logs]$ ls
app.2020-06-14.log
[fancy@node102 logs]$ ls
app.2020-06-14.log
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在森林中麋了鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值