电商数仓——日志数据采集

离线数仓同步数据

Flume需将Kafka中topic_log的数据发往HDFS。并且对每天产生的用户行为日志进行区分,将不同天的数据发往HDFS不同天的路径。

选择KafkaSource、FileChannel、HDFSSink进行数据传输。

一、日志消费Flume配置实操

1、创建Flume配置文件(用于从Kafka读取数据并将其写入HDFS)

在flume目录下创建job目录,在job下创建kafka_to_hdfs_log.conf文件

cd /opt/module/flume/

mkdir job

vim job/kafka_to_hdfs_log.conf

配置文件内容如下:

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


#配置source1

#指定source的类型,表示从kafka读取数据
a1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
#每次从Kafka读取的数据量大小为5000条
a1.sources.r1.batchSize = 5000
#两次批量读取之间的时间间隔为2000毫秒
a1.sources.r1.batchDurationMillis = 2000
#指定Kafka集群的地址和端口
a1.sources.r1.kafka.bootstrap.servers = hadoop102:9092,hadoop103:9092,hadoop104:9092
#指定要读取的Kafka主题为topic_log
a1.sources.r1.kafka.topics=topic_log
a1.sources.r1.interceptors = i1
#指定拦截器类型,用于确保时间戳正确
a1.sources.r1.interceptors.i1.type = com.dw.gmall.flume.interceptor.TimestampInterceptor$Builder


#配置channel

#channel的类型为file,表示使用文件作为数据传输的通道
a1.channels.c1.type = file
#指定checkpoint目录,用于记录数据的偏移量
a1.channels.c1.checkpointDir=/opt/module/flume/checkpoint/behavior1
#指定数据存储目录
a1.channels.c1.dataDirs = /opt/module/flume/data/behavior1
#单个文件的最大大小为2146435071字节
a1.channels.c1.maxFileSize = 2146435071
#channel的容量为000000条数据
a1.channels.c1.capacity = 1000000
#保持连接的时间为6秒
a1.channels.c1.keep-alive = 6


#配置sink

#指定sink的类型为hdfs,表示将数据写入HDFS
a1.sinks.k1.type = hdfs
#指定HDFS上的目标路径
#格式为/origin_data/gmall/log/topic_log/%Y-%m-%d
#其中%Y-%m-%d表示按年-月-日格式化的日期
a1.sinks.k1.hdfs.path = /origin_data/gmall/log/topic_log/%Y-%m-%d
#指定输出文件的前缀为log
a1.sinks.k1.hdfs.filePrefix = log
#false,不使用四舍五入的方式生成文件名
a1.sinks.k1.hdfs.round = false

#设置滚动间隔为10秒
a1.sinks.k1.hdfs.rollInterval = 10
#设置滚动大小为134217728字节
a1.sinks.k1.hdfs.rollSize = 134217728
#设置滚动计数为0,表示不限制滚动次数
a1.sinks.k1.hdfs.rollCount = 0


#控制输出文件类型
#设置输出文件类型为CompressedStream,表示使用压缩流
a1.sinks.k1.hdfs.fileType = CompressedStream
#设置压缩算法为gzip,将数据写入HDFS时使用gzip压缩
a1.sinks.k1.hdfs.codeC = gzip

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

二、编写拦截器(解决零点漂移问题)

零点漂移问题产生的原因:数据从日志文件到Flume的过程中可能经过了几秒的时间到了第二天,数据就被放到了第二天的路径下。

解决方法:在Flume的event中增加拦截器,用body的时间替换header的时间。

拦截器的作用:

1)检查确保JSON格式正确

2)确保时间戳正确

1、在idea里创建项目

2、在pom.xml文件中添加配置

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

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

3、创建com.dw.gmall.flume.interceptor包(包名要和flume配置中的拦截器类型名称一致)

4、在包下创建TimestampInterceptor类,代码如下

package com.atguigu.gmall.flume.interceptor;

import com.alibaba.fastjson.JSONObject;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

import java.util.List;
import java.util.Map;

#实现flume中Interceptor(拦截器)接口
public class TimestampInterceptor implements Interceptor {

    //初始化
    @Override
    public void initialize() {

    }
    
    //对单个事件(event)进行拦截处理
    @Override
    public Event intercept(Event event) {
    //1、获取header和body的数据
    Map<String, String> headers = event.getHeaders();
    String log = new String(event.getBody(), StandardCharsets.UTF_8);

    try {
        //2、将body的数据类型转成jsonObject类型(方便获取数据)
        JSONObject jsonObject = JSONObject.parseObject(log);

        //3、header中timestamp时间字段替换成日志生成的时间戳(解决数据漂移问题)
        //从JSONObject中获取时间戳字段js
        String ts = jsonObject.getString("ts");
        //将其添加到header中的"timestamp"字段,以替换原有的时间戳
        headers.put("timestamp", ts);

        //最后返回处理后的event
        return event;

    } catch (Exception e) {    //如果在处理过程中发生异常,将打印异常信息并返回null
        e.printStackTrace();
        return null;
    }
}

拦截event集合(多个event)
@Override
public List<Event> intercept(List<Event> list) {
    Iterator<Event> iterator = list.iterator();
    while (iterator.hasNext()) {
        Event event = iterator.next();
        //如果event为null将其移除
        if (intercept(event) == null) {
            iterator.remove();
        }
    }
    return list;
}

    @Override
    public void close() {

    }


    //实现了Interceptor.Builder接口,用于构建TimestampInterceptor实例
    public static class Builder implements Interceptor.Builder {
        //build()方法返回一个新的TimestampInterceptor对象
        @Override
        public Interceptor build() {
            return new TimestampInterceptor();
        }

        @Override
        public void configure(Context context) {
        }
    }
}

5、打包

双击package

将打包好的jar包放入flume的lib目录下(只需放入文件名最长的jar包)

三、日志消费Flume测试

1、启动Zookeeper、Kafka、HDFS

2、启动日志采集Flume

bin/flume-ng agent -n a1 -c conf/ -f job/file_to_kafka.conf

或使用脚本启动(需要先配置好脚本文件)f1.sh start

3、启动日志消费Flume

(1)bin/flume-ng agent -n a1 -c conf/ -f job/kafka_to_hdfs_log.conf

(2)日志消费启停脚本

在用户目录下的bin目录下创建脚本f2.sh

vim 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/kafka_to_hdfs_log.conf >/dev/null 2>&1 &"
;;
"stop")

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

增加脚本执行权限

chmod +x f2.sh

启动:f2.sh start

停止:f2.sh stop

4、生成模拟数据

java -jar  生成数据的jar包名称

如:java -jar gmall-remake-mock-2023-02-17.jar

或脚本启动:lg.sh

5、观察HDFS是否出现数据

在浏览器输入: 主机ip:9870   进入HDFSUI界面

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值