大数据技术——实战项目:广告数仓(第三部分)

目录

第6章 广告数仓采集通道

6.1 模拟数据准备

6.1.1 广告管理平台数据库

6.1.2 曝光点击监测数据

6.2 广告管理平台数据采集

6.2.1 数据库同步工具之DataX

6.2.2 数据采集通道

6.2.3 DataX配置文件

6.2.4 DataX配置文件生成

6.2.5 测试生成的DataX配置文件

6.2.6 全量数据同步脚本

6.3 曝光点击监测数据采集

6.3.1 采集通道安装

6.3.2 数据采集通道

6.3.3 日志采集Flume

6.3.3.1 配置概述

6.3.3.2 配置实操

6.3.3.3 测试

6.3.3.4 启停脚本

6.3.4 日志消费Flume

6.3.4.1 配置概述

6.3.4.2 配置实操

6.3.4.3 测试

6.3.4.4 启停脚本


第6章 广告数仓采集通道

6.1 模拟数据准备

6.1.1 广告管理平台数据库

1)数据库概述

广告管理平台中核心的几张表结构如下:

1ads(广告表)

id

(广告编号)

product_id

(商品id)

material_id

(素材id)

group_id

(广告组id)

ad_name

(广告名称)

material_url

(素材地址)

0

329375909941

712337489641

8

XXX

XXX

1

130171159227

519572879265

7

XXX

XXX

2

251005109937

294923573889

10

XXX

XXX

2platform_info(推广平台表)

id

(平台id)

platform

(平台标识)

platform_alias_zh

(平台中文名称)

1

tencent

腾讯广告

2

baidu

百度推广

3

juliang

巨量

3product(商品表)

id

(商品id)

name

(商品名称)

price

(商品价格)

659417

【精选】葡萄柚台湾葡萄蜜柚皮薄平和甜蜜柚当季新鲜水果批发包邮

9.9

1214894

【精品】正宗赣南脐橙新鲜橙子江西甜橙孕妇水果冰糖果冻香橙包邮

14.8

5307635

特辣朝天椒小米椒微辣中辣干辣椒超辣特香散装干货500

17.5

4ads_platform(广告投放表)

id

(编号)

ad_id

(广告id)

platform_id

(平台id)

create_time

(开始投放时间)

cancel_time

(取消投放时间)

1

0

3

XXX

XXX

2

0

2

XXX

XXX

3

1

3

XXX

XXX

5server_host(日志服务器列表)

id

(编号)

ipv4

(服务器ip)

1

203.195.136.146

2

103.250.32.51

3

203.90.0.54

2)模拟数据准备

1)安装MySQL数据库

1.  安装包准备

                1)上传mysql文件夹及里面所有内容上传到/opt/software/mysql目录下

2.  安装MySQL

1)如果是阿里云服务器按照如下步骤执行

说明:由于阿里云服务器安装的是Linux最小系统版,没有如下工具,所以需要安装。

(1)卸载MySQL依赖,虽然机器上没有装MySQL,但是这一步不可少

[atguigu@hadoop102 mysql]# sudo yum remove mysql-libs

(2)下载依赖并安装

[atguigu@hadoop102 mysql]# sudo yum install libaio

[atguigu@hadoop102 mysql]# sudo yum -y install autoconf

2)切换到hadoop102的root用户

[atguigu@hadoop102 mysql]$ su root

3)执行/opt/software/mysql/目录下install_mysql.sh

内容如下

[root@hadoop102 mysql]# vim install_mysql.sh

#!/bin/bash
set -x
[ "$(whoami)" = "root" ] || exit 1
[ "$(ls *.rpm | wc -l)" = "7" ] || exit 1
test -f mysql-community-client-8.0.31-1.el7.x86_64.rpm && \
test -f mysql-community-client-plugins-8.0.31-1.el7.x86_64.rpm && \
test -f mysql-community-common-8.0.31-1.el7.x86_64.rpm && \
test -f mysql-community-icu-data-files-8.0.31-1.el7.x86_64.rpm && \
test -f mysql-community-libs-8.0.31-1.el7.x86_64.rpm && \
test -f mysql-community-libs-compat-8.0.31-1.el7.x86_64.rpm && \
test -f mysql-community-server-8.0.31-1.el7.x86_64.rpm || exit 1

# 卸载MySQL
systemctl stop mysql mysqld 2>/dev/null
rpm -qa | grep -i 'mysql\|mariadb' | xargs -n1 rpm -e --nodeps 2>/dev/null
rm -rf /var/lib/mysql /var/log/mysqld.log /usr/lib64/mysql /etc/my.cnf /usr/my.cnf

set -e
# 安装并启动MySQL
yum install -y *.rpm >/dev/null 2>&1
systemctl start mysqld

#更改密码级别并重启MySQL
sed -i '/\[mysqld\]/avalidate_password.length=4\nvalidate_password.policy=0' /etc/my.cnf
systemctl restart mysqld

# 更改MySQL配置
tpass=$(cat /var/log/mysqld.log | grep "temporary password" | awk '{print $NF}')
cat << EOF | mysql -uroot -p"${tpass}" --connect-expired-password >/dev/null 2>&1
set password='000000';
update mysql.user set host='%' where user='root';

alter user 'root'@'%' identified with mysql_native_password by '000000';

flush privileges;
EOF

执行脚本。

[root@hadoop102 mysql]# sh install_mysql.sh

4)退出root用户到atguigu用户

[root@hadoop102 mysql]# exit

2)使用MySQL可视化客户端连接数据库

3)通过DBeaver创建数据库

设置数据库名称为ad,编码为utf8mb4,排序规则为utf8mb4_general_ci

3)导入数据库结构脚本(init.sql

6.1.2 曝光点击监测数据

1)日志格式概述

        前文提到过,监测数据由媒体方通过HTTP请求发送到我们的日志服务器。日志服务器接受到请求后会将数据落盘到日志文件中。文件中的每行日志格式如下:

time_local\u0001 request_method\u0001request_uri\u0001status\u0001server_addr

日志中每部分的含义如下:

字段

说明

示例数据

\u0001分隔符,Unicode中的一个不可见字符,用作分隔符,可避免与文本中的字符冲突,同时也是Hive中列分隔符的默认值

time_local

日志服务器收到监测数据上报请求的时间2023-01-07 00:00:10
request_methodHTTP请求方法,常用的方法有GET、POST,GET请求通常用于向Web服务器请求数据,POST通常用于向Web服务器提交数据处理请求GET
request_uri请求路径,这部分内容包括了媒体上报的监测数据的核心内容。122.189.79.23&ua=Mozilla/5.0%20 (Windows%20NT%2010.0)%20Appl eWebKit/537.36%20(KHTML,%20lik e%20Gecko)%20Chrome/40.0.2214 .93%20Safari/537.36&device_id= d4b8f3898515056278ccf78a7a2cca2 d&os_type=Android"
status日志服务器的响应状态码,200表示响应成功200
server_addr日志服务器自身的IP地址203.195.136.146

        其中,request_uri请求路径的内容最为重要,下面对该部分内容做重点介绍:

        请求的路径,格式如下

/ad/<platform>/<event_type>?id=<id>&t=<ts>&ip=<ip>&ua=<ua>&device_id=<device_id>&os_type=<os_type>

路径参数

参数名

含义

platform

tencentbaidujulang表示不同的广告投放平台

event_type

impression表示曝光事件,click表示点击事件

查询参数

参数

含义

id

广告id

t

毫秒时间戳,曝光或者点击时间的发生时间

ip

访问广告的用户客户端ipv4地址

ua

访问广告的用户客户端的user-agent

device_id

访问广告的用户客户端的设备id

os_type

访问广告的用户客户端的操作系统类型

2)数据模拟器使用说明

(1)上传数据模拟器jar包

        我们模拟hadoop102和hadoop103为接受监测数据的服务器,因此我们需在这两台节点上传日志模拟器。

        在hadoop102、hadoop103分别创建/opt/module/ad_mock路径,并上传资料中的NginxDataGenerator-1.0-SNAPSHOT-jar-with-dependencies.jar 以及nginxLogGen.setting文件到该路径中。

(2)修改模拟器配置文件

##############################
# 数据库配置
##############################

# jdbc链接,主要用来指定机器和端口
jdbcUrl = jdbc:mysql://hadoop102:3306?useSSL=false

# 用户名
user = root

# 密码
password = 000000

# 数据库
database = ad

# 连接数据库要用的驱动类
driver = com.mysql.jdbc.Driver

##############################
# 目标地址与文件名
##############################

# 目标路径
targetPath = /opt/module/ad_mock/log

# 文件名称
fileName = access.log

##############################
# 数据生成器行为控制
##############################

# 数据基数[整数](基数越大,单线程的数据量越大,但只能粗略控制)
baseDataNum = 100

# 线程数[整数](运用CPU的多核能力,同时数据量会翻倍)
threadNum = 4

# 数据的开始时间
startTime = 2023-01-07 00:00:00

# 数据的结束时间
endTime = 2023-01-08 00:00:00

###############################
# 数据比重[浮点数] (0或注释为关闭)
##############################

# ip固定且周期访问的浏览器
cycleBrowser = 0.1

# 设备id固定且周期访问的移动设备
cycleDevice = 0.1

# ip固定且快速访问的浏览器
fastFixedIpBrowser = 0.1

# 设备id固定且快速访问的移动设备
fastFixedIdDevice = 0.1

# 正常浏览器设备
normalBrowser = 0.1

# 正常移动设备
normalDevice = 0.4

# 携带爬虫ua的浏览器请求
botBrowser = 0.1

##############################
# 生成器日志级别
##############################

# DEBUG,INFO,WARN,ERROR
logLevel = INFO

##############################
# 仅为测试使用,标注每条数据来自哪个类,false不加,true会加
##############################

# true or false
whereDataFrom = false

(3)测试模拟器

进入/opt/module/ad_mock目录,并执行以下命令。

[atguigu@hadoop102 ad_mock]$ java -jar NginxDataGenerator-1.0-SNAPSHOT-jar-with-dependencies.jar

(4)创建一键生成数据脚本

在hadoop102节点的/home/atguigu/bin/目录下创建ad_mock.sh文件。

[atguigu@hadoop102 ~]$ vim /home/atguigu/bin/ad_mock.sh

填入以下内容。

#!/bin/bash

for i in hadoop102 hadoop103
do
echo "========== $i =========="
        ssh $i "cd /opt/module/ad_mock ; java -jar /opt/module/ad_mock/NginxDataGenerator-1.0-SNAPSHOT-jar-with-dependencies.jar >/dev/null  2>&1 &"
done

增加执行权限。

[atguigu@hadoop102 ~]$ chmod +x /home/atguigu/bin/ad_mock.sh

(5)测试数据生成脚本

执行ad_mock.sh文件。

[atguigu@hadoop102 ~]$ ad_mock.sh

观察hadoop102,hadoop103两台节点是否有数据生成。

6.2 广告管理平台数据采集

6.2.1 数据库同步工具之DataX

本项目中采用的数据库同步工具为DataX,DataX的安装和使用可参考以下博客文章。

大数据技术——DataX的使用与优化-CSDN博客

6.2.2 数据采集通道

广告管理平台的数据库中的数据,主要用作广告数仓的维度表,故此处采用DataX进行每日全量同步。

6.2.3 DataX配置文件

我们需要为每张全量表编写一个DataX的json配置文件,此处以product表为例,配置文件内容如下:

{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "column": [
                            "id",
                            "name",
                            "price"
                        ],
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://hadoop102:3306/ad"
                                ],
                                "table": [
                                    "product"
                                ]
                            }
                        ],
                        "password": "000000",
                        "splitPk": "",
                        "username": "root"
                    }
                },
                "writer": {
                    "name": "hdfswriter",
                    "parameter": {
                        "column": [
                            {
                                "name": "id",
                                "type": "bigint"
                            },
                            {
                                "name": "name",
                                "type": "string"
                            },
                            {
                                "name": "price",
                                "type": "double"
                            }
                        ],
                        "compress": "gzip",
                        "defaultFS": "hdfs://hadoop102:8020",
                        "fieldDelimiter": "\t",
                        "fileName": "product",
                        "fileType": "text",
                        "path": "${targetdir}",
                        "writeMode": "append"
                    }
                }
            }
        ],
        "setting": {
            "errorLimit": {
                "percentage": 0.02,
                "record": 0
            },
            "speed": {
                "channel": 3
            }
        }
    }
}

        注:由于目标路径包含一层日期,用于对不同天的数据加以区分,故path参数并未写死,需在提交任务时通过参数动态传入,参数名称为targetdir

6.2.4 DataX配置文件生成

1DataX配置文件生成器使用

DataX配置文件生成器可参考推文:大数据技术——DataX配置文件生成器-CSDN博客

2将生成器上传到服务器的/opt/module/gen_datax_config目录

[atguigu@hadoop102 ~]$ mkdir /opt/module/gen_datax_config

[atguigu@hadoop102 ~]$ cd /opt/module/gen_datax_config

3)上传生成器

4修改configuration.properties配置

mysql.username=root
mysql.password=000000
mysql.host=hadoop102
mysql.port=3306
mysql.database.import=ad
# mysql.database.export=ad_report
mysql.tables.import=
# mysql.tables.export=
is.seperated.tables=0
hdfs.uri=hdfs://hadoop102:8020
import_out_dir=/opt/module/datax/job/import
# export_out_dir=

5执行

[atguigu@hadoop102 gen_datax_config]$ java -jar datax-config-generator-1.0-SNAPSHOT-jar-with-dependencies.jar

6观察结果

6.2.5 测试生成的DataX配置文件

以Product为例,测试用脚本生成的配置文件是否可用。

1)创建目标路径

由于DataX同步任务要求目标路径提前存在,故需手动创建路径,当前Product表的目标路径应该为/origin_data/ad/db/product_full/2023-01-07

[atguigu@hadoop102 bin]$ hadoop fs -mkdir -p /origin_data/ad/db/product_full/2023-01-07

2)执行DataX同步命令

[atguigu@hadoop102 bin]$ python /opt/module/datax/bin/datax.py -p"-Dtargetdir=/origin_data/ad/db/product_full/2023-01-07" /opt/module/datax/job/import/ad.product.json

3)观察同步结果

观察HDFS目标路径是否出现数据。

6.2.6 全量数据同步脚本

        为方便使用以及后续的任务调度,此处编写一个全量表数据同步脚本。

1)在~/bin目录创建mysql_to_hdfs_full.sh

[atguigu@hadoop102 bin]$ vim ~/bin/ad_mysql_to_hdfs_full.sh

脚本内容如下。

#!/bin/bash

DATAX_HOME=/opt/module/datax

# 如果传入日期则do_date等于传入的日期,否则等于前一天日期
if [ -n "$2" ] ;then
    do_date=$2
else
    do_date=`date -d "-1 day" +%F`
fi

#处理目标路径,此处的处理逻辑是,如果目标路径不存在,则创建;若存在,则清空,目的是保证同步任务可重复执行
handle_targetdir() {
  hadoop fs -test -e $1
  if [[ $? -eq 1 ]]; then
    echo "路径$1不存在,正在创建......"
    hadoop fs -mkdir -p $1
  else
    echo "路径$1已经存在"
    fs_count=$(hadoop fs -count $1)
    content_size=$(echo $fs_count | awk '{print $3}')
    if [[ $content_size -eq 0 ]]; then
      echo "路径$1为空"
    else
      echo "路径$1不为空,正在清空......"
      hadoop fs -rm -r -f $1/*
    fi
  fi
}

#数据同步
#参数:arg1-datax 配置文件路径;arg2-源数据所在路径
import_data() {
  handle_targetdir $2
  python $DATAX_HOME/bin/datax.py -p"-Dtargetdir=$2" $1
}

case $1 in
"product")
  import_data /opt/module/datax/job/import/ad.product.json /origin_data/ad/db/product_full/$do_date
  ;;
"ads")
  import_data /opt/module/datax/job/import/ad.ads.json /origin_data/ad/db/ads_full/$do_date
  ;;
"server_host")
  import_data /opt/module/datax/job/import/ad.server_host.json /origin_data/ad/db/server_host_full/$do_date
  ;;
"ads_platform")
  import_data /opt/module/datax/job/import/ad.ads_platform.json /origin_data/ad/db/ads_platform_full/$do_date
  ;;
"platform_info")
  import_data /opt/module/datax/job/import/ad.platform_info.json /origin_data/ad/db/platform_info_full/$do_date
  ;;
"all")
  import_data /opt/module/datax/job/import/ad.product.json /origin_data/ad/db/product_full/$do_date
  import_data /opt/module/datax/job/import/ad.ads.json /origin_data/ad/db/ads_full/$do_date
  import_data /opt/module/datax/job/import/ad.server_host.json /origin_data/ad/db/server_host_full/$do_date
  import_data /opt/module/datax/job/import/ad.ads_platform.json /origin_data/ad/db/ads_platform_full/$do_date
  import_data /opt/module/datax/job/import/ad.platform_info.json /origin_data/ad/db/platform_info_full/$do_date
  ;;
esac

2)为mysql_to_hdfs_full.sh增加执行权限

[atguigu@hadoop102 bin]$ chmod 777 ~/bin/mysql_to_hdfs_full.sh

3)测试同步脚本

[atguigu@hadoop102 bin]$ mysql_to_hdfs_full.sh all 2023-01-07

4)检测同步结果

查看HDFS目标路径是否出现全量表数据,全量表共5张。

6.3 曝光点击监测数据采集

6.3.1 采集通道安装

采集通道涉及到的组件有Flume和Kafka,故需要先完成两者的安装,安装步骤可参考下列文档。

1Zookeeper安装

参考博客:大数据技术——zookeeper的安装部署与启停脚本-CSDN博客

2Kafka安装

参考博客:大数据技术——Kafka的安装部署与启停脚本-CSDN博客

3Flume安装

三台节点均需要安装Flume,可先找如下文档在一台节点安装,完成后再进行分发。

参考博客:大数据技术——Flume的安装与部署-CSDN博客

6.3.2 数据采集通道

        按照规划,需要采集的广告监测日志文件分布在hadoop102,hadoop103两台日志服务器,故需要在两台节点部署Flume实时采集,Flume采集到的数据会发往Kafka集群,后再由hadoop104节点的Flume实例消费Kafka数据,并将数据写入HDFS相应目录。

6.3.3 日志采集Flume

6.3.3.1 配置概述

        hadoop102和hadoop103的两个Flume实例主要负责采集日志文件内容,并将数据发往Kafka,故Source可选择TailDirSource,Channel可选择KafkaChannel,不使用Sink。

其中关键配置如下:

6.3.3.2 配置实操

1)创建Flume配置文件

在hadoop102节点的Flume的job目录下创建ad_file_to_kafka.conf

[atguigu@hadoop102 flume]$ mkdir job

[atguigu@hadoop102 flume]$ vim job/ad_file_to_kafka.conf

2)配置文件内容如下

#定义组件
a1.sources = r1
a1.channels = c1

#配置source
a1.sources.r1.type = TAILDIR
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /opt/module/ad_mock/log/.*
a1.sources.r1.positionFile = /opt/module/flume/taildir_position.json

#配置channel
a1.channels.c1.type = org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c1.kafka.bootstrap.servers = hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.channels.c1.kafka.topic = ad_log

#组装 
a1.sources.r1.channels = c1
6.3.3.3 测试

1)启动ZookeeperKafka集群

2)启动hadoop102的日志采集Flume

[atguigu@hadoop102 flume]$ bin/flume-ng agent -n a1 -c conf/ -f job/ad_file_to_kafka.conf -Dflume.root.logger=info,console

3)启动一个KafkaConsole-Consumer

[atguigu@hadoop102 kafka]$ bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic ad_log

4)生成模拟数据

[atguigu@hadoop102 ~]$ ad_mock.sh

5)观察Kafka消费者是否能消费到数据

6.3.3.4 启停脚本

1分发日志采集Flume配置文件

若上述测试通过,需将hadoop102节点的Flume的配置文件,向另一台日志服务器也发送一份。

[atguigu@hadoop102 flume]$ scp -r job hadoop103:/opt/module/flume/

2)方便起见,此处编写一个日志采集Flume进程的启停脚本

(1)在hadoop102节点的/home/atguigu/bin目录下创建脚本ad_f1.sh

[atguigu@hadoop102 bin]$ vim ad_f1.sh

在脚本中填写如下内容。

#!/bin/bash

case $1 in
"start"){
        for i in hadoop102 hadoop103
        do
                echo " --------启动 $i 采集flume-------"
                ssh $i "nohup /opt/module/flume/bin/flume-ng agent -n a1 -c /opt/module/flume/conf/ -f /opt/module/flume/job/ad_file_to_kafka.conf >/dev/null 2>&1 &"
        done
};; 
"stop"){
        for i in hadoop102 hadoop103
        do
                echo " --------停止 $i 采集flume-------"
                ssh $i "ps -ef | grep ad_file_to_kafka | grep -v grep |awk  '{print \$2}' | xargs -n1 kill -9 "
        done

};;
esac

(2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod x ad_f1.sh

(3)f1启动

[atguigu@hadoop102 module]$ ad_f1.sh start

(4)f1停止

[atguigu@hadoop102 module]$ ad_f1.sh stop

6.3.4 日志消费Flume

6.3.4.1 配置概述

该Flume实例主要负责消费Kafka中的数据并发往HDFS。并且对每天产生对应用户行为日志进行区分,将不同天的数据发往HDFS不同天的路径。

Source、Channel和Sink可分别选用KafkaSource、FileChannel、HDFSSink。

关键配置如下:

6.3.4.2 配置实操

1)创建Flume配置文件

hadoop104节点Flume的job目录下创建ad_kafka_to_hdfs.conf文件。

[atguigu@hadoop104 flume]$ mkdir job

[atguigu@hadoop104 flume]$ vim job/ad_kafka_to_hdfs.conf

2)配置文件内容如下

#定义组件
a1.sources=r1
a1.channels=c1
a1.sinks=k1

#配置source1
a1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
a1.sources.r1.batchSize = 1000
a1.sources.r1.batchDurationMillis = 2000
a1.sources.r1.kafka.bootstrap.servers = hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.sources.r1.kafka.topics = ad_log
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = com.atguigu.ad.flume.interceptor.TimestampInterceptor$Builder

#配置channel
a1.channels.c1.type = file
a1.channels.c1.checkpointDir = /opt/module/flume/checkpoint/behavior1
a1.channels.c1.dataDirs = /opt/module/flume/data/behavior1
a1.channels.c1.maxFileSize = 2146435071
a1.channels.c1.capacity = 1000000
a1.channels.c1.keep-alive = 6

#配置sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /origin_data/ad/log/ad_log/%Y-%m-%d
a1.sinks.k1.hdfs.filePrefix = log
a1.sinks.k1.hdfs.round = false


a1.sinks.k1.hdfs.rollInterval = 10
a1.sinks.k1.hdfs.rollSize = 134217728
a1.sinks.k1.hdfs.rollCount = 0

#控制输出文件类型
a1.sinks.k1.hdfs.fileType = CompressedStream
a1.sinks.k1.hdfs.codeC = gzip

#组装 
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

3编写Flume拦截器

(1)创建一个Maven项目,在pom.xml中添加如下依赖。

<dependencies>
    <dependency>
        <groupId>org.apache.flume</groupId>
        <artifactId>flume-ng-core</artifactId>
        <version>1.10.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

(2)在com.atguigu.ad.flume.interceptor包下创建TimestampInterceptor类。

package com.atguigu.ad.flume.interceptor;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TimestampInterceptor implements Interceptor {

    private Pattern pattern;

    @Override
    public void initialize() {
        pattern = Pattern.compile(".*t=(\\d{13}).*");
    }

    @Override
    public Event intercept(Event event) {

        String log = new String(event.getBody(), StandardCharsets.UTF_8);

        //1.移除每个字段的双引号
        //去掉前后两个双引号
        String subLog = log.substring(1, log.length() - 1);

        //去掉各分隔符两侧的双引号,\u0001表示分隔符
        String result = subLog.replaceAll("\"\u0001\"", "\u0001");
        event.setBody(result.getBytes(StandardCharsets.UTF_8));

        //2.提取时间戳(利用正则表达式的分组捕获功能实现)
        Matcher matcher = pattern.matcher(result);
        if (matcher.matches()) {
            String ts = matcher.group(1);
            event.getHeaders().put("timestamp", ts);
        } else {
            return null;
        }
        return event;
    }

    @Override
    public List<Event> intercept(List<Event> events) {

        Iterator<Event> iterator = events.iterator();
        while (iterator.hasNext()) {
            Event next = iterator.next();
            Event intercept = intercept(next);
            if (intercept == null) {
                iterator.remove();
            }
        }

        return events;
    }
    @Override
    public void close() {

    }

    public static class Builder implements Interceptor.Builder{
        @Override
        public Interceptor build() {
            return new TimestampInterceptor();
        }

        @Override
        public void configure(Context context) {

        }
    }
}

(3)打包

(4)将打好的包放入到hadoop104的/opt/module/flume/lib目录下。

6.3.4.3 测试

1)启动zookeeperkafka集群。

2)启动日志采集Flume

[atguigu@hadoop102 ~]$ ad_f1.sh start

3)启动hadoop104的日志消费Flume

[atguigu@hadoop104 flume]$ bin/flume-ng agent -n a1 -c conf/ -f job/ad_kafka_to_hdfs.conf -Dflume.root.logger=info,console

4)生成模拟数据

[atguigu@hadoop102 ~]$ ad_mock.sh

5)观察HDFS是否出现数据

6.3.4.4 启停脚本

若上述测试通过,为方便,此处创建一个Flume的启停脚本。

1)在hadoop102节点的/home/atguigu/bin目录下创建脚本ad_f2.sh

[atguigu@hadoop102 bin]$ vim ad_f2.sh

        在脚本中填写如下内容。

#!/bin/bash

case $1 in
"start")
        echo " --------启动 hadoop104 日志数据flume-------"
        ssh hadoop104 "nohup /opt/module/flume/bin/flume-ng agent -n a1 -c /opt/module/flume/conf -f /opt/module/flume/job/ad_kafka_to_hdfs.conf >/dev/null 2>&1 &"
;;
"stop")

        echo " --------停止 hadoop104 日志数据flume-------"
        ssh hadoop104 "ps -ef | grep ad_kafka_to_hdfs | grep -v grep |awk '{print \$2}' | xargs -n1 kill"
;;
esac

2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod +x ad_f2.sh

3f2启动

[atguigu@hadoop102 module]$ ad_f2.sh start

4f2停止

[atguigu@hadoop102 module]$ ad_f2.sh stop

前面章节部分:

大数据项目——实战项目:广告数仓(第一部分)-CSDN博客

大数据项目——实战项目:广告数仓(第二部分)-CSDN博客

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值