大数据开发快速入门Flume(第十三篇)

790 阅读11分钟

一、什么是Flume

Flume是一个高可用、高可靠,分布式的海量日志采集、聚合和传输的系统,能够有效的收集、聚合、移动大量的日志数据。通俗来讲:Flume是一个很靠谱、很方便、很强大的日志采集工具

它是大数据领域数据采集最常用的一个框架

1.1、为什么流行?

因为Flume采集数据不需要写一行代码,只需要在配置文件中随便写几行配置就可以正常运行了。

Flume

1.2、Flume特性
  1. 它有一个简单、灵活的基于流的数据流结构
  2. 具有负载均衡机制和故障转移机制
  3. 一个简单可扩展的数据模型(Source、Channel、Sink)
1.3、Flume高级应用场景
1.3.1、采集一份数据重复输出到不同的目的地中

Flume高级应用

应用场景介绍

启动2个Flume代理,代理1的Source后面接了3个Channel,表示Source读取到的数据会重复发送给每个Channel,每个Channel中的数据都是一样的。每个Channel都接了一个Sink。这三个Sink负责读取对应Channel中的数据,并且把数据输出到不同的目的地。

  • sink1负责把数据写到hdfs中
  • sink2负责把数据写到一个java消息服务队列中
  • sink3负责把数据写到另一个Agent
1.3.2、Flume汇聚功能

Flume汇聚功能

应用场景介绍

启动4个代理,左边三个代理都是负责采集对应web服务器中的日志数据,数据采集过来之后统一发送给agent4,最后agent4进行统一汇总,最终写入到hdfs。

  1. 架构优点:

    • 如果要修改最终数据输出目的地,只需要修改agent4中的sink,不需要修改其他
  2. 架构缺点:

    • agent4存在性能瓶颈,会导致数据处理过慢
    • 还可能存在单点故障问题

二、Flume三大核心组件

Flume三大核心组件:

  1. Source:数据源
  2. Channel:临时存储数据的管道
  3. Sink:目的地
2.1、Source

Source组件可以指定让Flume读取哪里的数据,然后将数据传递给后面的Channel。Flume内置支持读取很多种数据源,基于文件、基于目录、基于TCP\UDP端口、基于HTTP、基于Kafka等数据源,也支持自定义

  1. Exec Source(常用)

    实现文件监控,可以实时监控文件中的新增内容,类似于Linux中tail -f效果。需要主要tail -Ftail -f的区别

    • tail -F:根据文件名进行追踪,当文件名改名或者删除后,如果再次创建相同的文件名,会继续追踪

      (等同于:-follow=name ---retry)

    • tail -f:根据文件描述符进行追踪,当文件名改名或者删除,停止追踪。

      (等同于:-follow=descriptor)

    在实际工作中,我们Java应用的日志会采用log4j记录。项目日志文件名格式是:xxx(项目名).log。每天凌晨的时候,log4j会对日志进行归档操作将日志文件名修改为:xxx(项目名)-yyyyMMdd.log。这时候如果要一直监控项目日志文件。就需要使用tail -F

  2. NetCat TCP/UDP Source

    采集指定端口(tcp、udp)的数据,可以读取流经端口的每一行数据

  3. Spooling Directory Source

    采集文件夹里新增的文件

  4. Kafka Source(常用)

    从Kafka消息队列中采集数据

2.2、Channel

接收Source发出的数据,可以把Channel理解为一个临时存储数据的管道。Channel类型有很多:内存、文件、内存+文件、Jdbc等。

Channel类型分类:

  1. Memory Channel

    使用内存作为数据的存储

    优点:

    • 效率高。因为不涉及磁盘IO

    缺点:

    • 可能会丢数据,如果Flume的agent宕机了,那么Channel中的数据就丢失了
    • 内存是有限的,会存在内存不够用的情况
  2. File Channel(最常用)

    使用文件作为数据的存储

    优点:

    • 数据不会丢失

    缺点:

    • 效率相对内存来说优点慢,但是这个慢也不是特别慢
  3. Spilable Memory Channel

    使用内存和文件作为数据存储,先把数据存到内存中,如果内存中数据达到阀值再Flush到文件中

    优点:

    • 解决了内存不够的问题

    缺点:

    • 还是存在丢失数据的风险
2.3、Sink

从Channel中读取数据并存储到指定目的地。Sink的表现形式有很多:打印到控制台、HDFS、Kafka等。Channel的数据直到进入目的地才会删除,当Sink写入目的地失败后,可以自动重写,不会造成数据丢失,这块是有一个事务保证的。

常用的sink组件

  1. Logger Sink

    将数据作为日志处理,可以选择打印到控制台或者写到文件中,这个主要在测试的时候使用

  2. HDFS Sink

    将数据传输到HDFS中,这个是比较常见的,主要针对离线计算的场景

  3. Kafka Sink

    将数据发送到Kafka消息队列中,这个是比较常见的,主要针对实时计算场景,数据不落盘,实时传输,最后使用实时计算框架直接处理。

三、安装Flume

官方网站:flume.apache.org/

image-20220918152053715

3.1、安装配置
  1. 下载安装包上传到linux机器上

  2. 解压flume安装包

    tar -zxvf apache-flume-1.10.1-bin.tar.gz

  3. 修改flume的env环境变量配置文件

    在flume的conf目录下,修改flume-env.sh.template的名称,去掉后缀template

    mv flume-env.sh.template flume-env.sh

  4. 这样可以安装好了flume

四、Flume的快速入门

1.10.1版本的对于的文档地址:flume.apache.org/releases/co…

官网给的示范例子:flume.apache.org/releases/co…

# Name the components on this agent
# 定义source名字、sink名字、channel名字
a1.sources = r1
a1.sinks = k1
a1.channels = c1
​
# Describe/configure the source
# 配置source相关参数
a1.sources.r1.type = netcat
#可以修改为 0.0.0.0 代表可以任意机器访问
a1.sources.r1.bind = localhost 
a1.sources.r1.port = 44444# Describe the sink
# 配置sink相关参数
a1.sinks.k1.type = logger
​
# Use a channel which buffers events in memory
# 配置channel相关参数
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100# Bind the source and sink to the channel
# 把三个组件链接起来,告诉source需要向哪个channel写入数据,告诉sink需要从哪个channel读取数据
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

总体步骤:

  1. 定义每个组件的名称
  2. 配置每个组件的参数
  3. 串起来每个组件
4.1、实战
  1. 在flume的conf目录创建一个配置文件

    vi demo.conf

    把上面的配置复制进去这个文件

  2. 修改flume的Jdk路径

    echo $JAVA_HOME

    在flume-env.sh修改

    export JAVA_HOME=/root/software/jdk1.8.0_341

  3. 配置log4j2的日志路径

    在flume目录下面创建logs目录

    修改conf目录下的log4j2.xml的property属性

    /root/software/apache-flume-1.10.1-bin/logs

  4. 启动agent

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

    后台启动运行

    nohup bin/flume-ng agent -c conf -f conf/demo.conf -n a1 &

    • --conf 指定flume配置文件的根目录(这边使用绝对路径)
    • --conf-file 指定agent对应的配置文件(包含source、channel、sink配置的文件)
    • --name 指定agent的名字
  5. 测试

    • 安装telnet

      yum install -y telnet

    • 连接flume

      telnet localhost 44444

  6. 查看日志

    image-20220918171752115

五、Flume案例

5.1、采集文件内容上传到HDFS
# Name the components on this agent
# 定义source名字、sink名字、channel名字
a1.sources = r1
a1.sinks = k1
a1.channels = c1
​
# Describe/configure the source
# 配置source相关参数
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /root/log/demoDir
​
# Use a channel which buffers events in memory
# 配置channel相关参数
a1.channels.c1.type = file
a1.channels.c1.checkpointDir =/root/software/apache-flume-1.10.1-bin/data/demoDir/checkponit
a1.channels.c1.dataDirs =/root/software/apache-flume-1.10.1-bin/data/demoDir/data
​
# Describe the sink
# 配置sink相关参数
a1.sinks.k1.type = hdfs
# 指定hdfs存储目录
a1.sinks.k1.hdfs.path = hdfs://192.168.234.100:9000/flume/demoDir
# 文件前缀。会在hdfs上生成的文件加上这个前缀
a1.sinks.k1.hdfs.filePrefix = demo-
# 默认SequenceFile。默认DataStream不会压缩数据
a1.sinks.k1.hdfs.fileType =DataStream
# 普通文本数据
a1.sinks.k1.hdfs.writeFormat =Text
# hdfs 1小时切分一个文件
a1.sinks.k1.hdfs.rollInterval =3600
# 默认1024,单位是字节。设置为0不按文件大小切 。这边设置128M
a1.sinks.k1.hdfs.rollSize =134217728
# 每隔10条数据切出一个文件。0表示不按数据条切文件
a1.sinks.k1.hdfs.rollCount =0
# Event输出到HDFS的文件名后缀
a1.sinks.k1.hdfs.fileSuffix = _${hdfsFileSuffix}.log
​
# Bind the source and sink to the channel
# 把三个组件链接起来,告诉source需要向哪个channel写入数据,告诉sink需要从哪个channel读取数据
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
  1. 创建目录

    mkdir -p /root/log/demoDir

  2. 创建测试数据

    vi demo.dat

    zhangsan 18 m lisi 20 m hanmeimei f

  3. 到flume的conf目录下,创建file-to-hdfs.conf

    vi file-to-hdfs.conf

  4. 启动hdfs

  5. 启动flume

    bin/flume-ng agent -c conf -f conf/file-to-hdfs.conf -n a1

  6. 这时候报错,因为本机安装的没有Hadoop环境,所以我们把这个flume拷贝到hadoop环境机器上

    scp -rq apache-flume-1.10.1-bin 192.168.234.100:/root/software/

  7. 校验

    此时发现demo.dat已经变成了demo.dat.COMPLETE

    image-20220918202401640

  8. 查看hdfs内容

    image-20220918202521655

    image-20220918202713339

    此时文件是.tmp后缀名的。此时没办法查看。两个解决方案:

    1. 停止Flume Agent

      停止Agent就会去掉了.tmp的标志。每次停止之前就会把所有的文件解除占用状态,下次启动的时候如果有新数据,则产生新的文件,这个其实模拟了一下自动切文件之后的效果

    2. 等待配置的1小时后

    查看文件内容

    hdfs dfs -cat /flume/demoDir/demo-.1663503765932

    image-20220918203209169

  9. 如果想要生成的文件名有一个后缀是.log。修改Agent配置,添加测试数据

    hdfs sink中的hdfs.fileSuffix参数

    # Event输出到HDFS的文件名后缀
    a1.sinks.k1.hdfs.fileSuffix = _${hdfsFileSuffix}.log
    
5.2、采集网站日志上传到HDFS

采集网站日志

  • Avro 是一种数据序列化系统,经过它序列化的数据传输起来效率更高。并且Avro Sink与Avro Source是无缝衔接的
  • ExecSource 是要实时读取文件中的新增数据

六、Flume的HDFS相关配置解析说明

type
    Sink类型为hdfs
​
hdfs.path
    HDFS存储路径,支持按照时间分区
    集群的NameNode名字:
        单节点:hdfs://主机名(ip):9000/%Y/%m/%d/%H
        HA集群:hdfs://nameservice(高可用NameNode服务名称)/%Y/%m/%d/%H
    
hdfs.filePrefix
    默认值:FlumeData
    Event输出到HDFS的文件名前缀
​
hdfs.fileSuffix
    Event输出到HDFS的文件名后缀
​
hdfs.inUsePrefix
    临时文件的文件名前缀
    Flume首先将Event输出到HDFS指定目录的临时文件中,再根据相关规则重命名为目标文件
​
hdfs.inUseSuffix
    默认值:.tmp
    临时文件名后缀
​
hdfs.rollInterval
    默认值:30
    间隔多久将临时文件滚动成最终目标文件,单位:秒
    如果设置为0,则表示不根据时间滚动文件
    注:滚动(roll)指的是,HDFS Sink将临时文件重命名成最终目标文件,并新打开一个临时文件来写数据
​
hdfs.rollSize
    默认值:1024
    当临时文件达到该大小时,滚动成目标文件,单位:byte
    该值设置为0,则表示文件不根据文件大小滚动生成
​
hdfs.rollCount
    默认值:10
    当Event数据达到该数量时,将临时文件滚动生成目标文件
    该值设置为0,则表示文件不根据Event数滚动生成
​
hdfs.idleTimeout
    默认值:0
    当目前被打开的临时文件在该参数指定的时间内,没有任何数据写入,则将该临时文件关闭并重命名成目标文件,单位:秒
    该值设置为0,则表示禁用此功能,不自动关闭临时文件
​
hdfs.round
    默认值:false
    用于HDFS文件按照时间分区,时间戳向下取整
​
hdfs.roundValue
    默认值:1
    当round设置为true,配合roundUnit时间单位一起使用,例如roundUnit值为minute
    该值设置为1则表示一分钟之内的数据写到一个文件中,相当于每一分钟生成一个文件
​
hdfs.roundUnit
    默认值:second
    按时间分区使用的时间单位,可以选择second(秒)、minute(分钟)、hour(小时)三种粒度的时间单位
    示例:
        a1.sinks.k1.hdfs.path = hdfs://nameservice/flume/events/%y/%m/%d/%H/%M
        a1.sinks.k1.hdfs.round = true
        a1.sinks.k1.hdfs.roundValue = 10
        a1.sinks.k1.hdfs.roundUnit = minute
        当时间为2022-04-05 17:38:59时候,hdfs.path依然会被解析为:/flume/events/2022/04/05/17/30
        因为设置的是舍弃10分钟内的时间,因此,该目录每10分钟新生成一个
​
hdfs.batchSize
    默认值:100
    每个批次刷写到HDFS的Event数量
​
hdfs.codeC
    默认值:不采用压缩
    文件压缩格式,目前支持的压缩格式有gzip、bzip2、lzo、lzop、snappy
​
hdfs.fileType
    默认值:SequenceFile
    文件类型,包括:SequenceFile、DataStream、CompressedStream
    该值设置为DataStream,则输出的文件不会进行压缩,不需要设置hdfs.codeC指定压缩格式。
    该值设置为CompressedStream,则对输出的文件进行压缩,需要设置hdfs.codeC指定压缩格式
​
hdfs.maxOpenFiles
    默认值:5000
    最大允许打开的HDFS文件数,当打开的文件数达到该值,则最早打开的文件将会被关闭
​
hdfs.minBlockReplicas
    默认值:HDFS副本数
    写入HDFS文件块的最小副本数
    该参数会影响文件的滚动配置,一般将该参数配置成1,才可以按照配置正确滚动文件
​
hdfs.writeFormat
    默认值:Writable
    文件的格式,目前可以选择Text或者Writable两种格式
​
hdfs.callTimeout
    默认值:10000
    操作HDFS文件的超时时间,如果需要写入HDFS文件的Event数比较大或者发生了打开、写入、刷新、关闭文件超时的问题,可以根据实际情况适当增大超时时间,单位:毫秒
​
hdfs.threadsPoolSize
    默认值:10
    每个HDFS Sink执行HDFS IO操作打开的线程数
​
hdfs.rollTimerPoolSize
    默认值:1
    HDFS Sink根据时间滚动生成文件时启动的线程数
​
hdfs.timeZone
    默认值:Local Time本地时间
    写入HDFS文件使用的时区
​
hdfs.useLocalTimeStamp
    默认值:false
    是否使用本地时间替换Event头信息中的时间戳
​
hdfs.closeTries
    默认值:0
    在发起关闭尝试后,尝试重命名临时文件的次数
    如果设置为1,表示重命名一次失败后不再继续尝试重命名操作,此时待处理的文件将处于打开状态,扩展名为.tmp
    如果设置为0,表示尝试重命名操作次数不受限制,直到文件最终被重命名成功
    如果close调用失败,文件可能仍然会处于打开状态,但是文件中的数据将保持完整,文件会在Flume重启后关闭
​
hdfs.retryInterval
    默认值:180 秒
    连续尝试关闭文件的时间间隔。如果设置为0或小于0的数,第一次尝试关闭文件失败后将不会继续尝试关闭文件,文件将保持打开状态或者以“.tmp”扩展名结尾的临时文件
    如果设置为0,表示不尝试,相当于于将hdfs.closeTries设置成1
​
serializer
    默认值:TEXT
    序列化方式,可选值有TEXT、avro_event或者实现EventSerializer.Builder接口的类
​
kerberosPrincipal
    HDFS安全认证kerberos配置
​
kerberosKeytab
    HDFS安全认证kerberos配置
​
proxyUser
    代理用户