一、什么是Flume
Flume是一个高可用、高可靠,分布式的海量日志采集、聚合和传输的系统,能够有效的收集、聚合、移动大量的日志数据。通俗来讲:Flume是一个很靠谱、很方便、很强大的日志采集工具。
它是大数据领域数据采集最常用的一个框架
1.1、为什么流行?
因为Flume采集数据不需要写一行代码,只需要在配置文件中随便写几行配置就可以正常运行了。
1.2、Flume特性
- 它有一个简单、灵活的基于流的数据流结构
- 具有负载均衡机制和故障转移机制
- 一个简单可扩展的数据模型(Source、Channel、Sink)
1.3、Flume高级应用场景
1.3.1、采集一份数据重复输出到不同的目的地中
应用场景介绍
启动2个Flume代理,代理1的Source后面接了3个Channel,表示Source读取到的数据会重复发送给每个Channel,每个Channel中的数据都是一样的。每个Channel都接了一个Sink。这三个Sink负责读取对应Channel中的数据,并且把数据输出到不同的目的地。
- sink1负责把数据写到hdfs中
- sink2负责把数据写到一个java消息服务队列中
- sink3负责把数据写到另一个Agent
1.3.2、Flume汇聚功能
应用场景介绍
启动4个代理,左边三个代理都是负责采集对应web服务器中的日志数据,数据采集过来之后统一发送给agent4,最后agent4进行统一汇总,最终写入到hdfs。
-
架构优点:
- 如果要修改最终数据输出目的地,只需要修改agent4中的sink,不需要修改其他
-
架构缺点:
- agent4存在性能瓶颈,会导致数据处理过慢
- 还可能存在单点故障问题
二、Flume三大核心组件
Flume三大核心组件:
- Source:数据源
- Channel:临时存储数据的管道
- Sink:目的地
2.1、Source
Source组件可以指定让Flume读取哪里的数据,然后将数据传递给后面的Channel。Flume内置支持读取很多种数据源,基于文件、基于目录、基于TCP\UDP端口、基于HTTP、基于Kafka等数据源,也支持自定义
-
Exec Source(常用)
实现文件监控,可以实时监控文件中的新增内容,类似于Linux中tail -f效果。需要主要tail -F和tail -f的区别
-
tail -F:根据文件名进行追踪,当文件名改名或者删除后,如果再次创建相同的文件名,会继续追踪
(等同于:-follow=name ---retry)
-
tail -f:根据文件描述符进行追踪,当文件名改名或者删除,停止追踪。
(等同于:-follow=descriptor)
在实际工作中,我们Java应用的日志会采用log4j记录。项目日志文件名格式是:xxx(项目名).log。每天凌晨的时候,log4j会对日志进行归档操作将日志文件名修改为:xxx(项目名)-yyyyMMdd.log。这时候如果要一直监控项目日志文件。就需要使用tail -F
-
-
NetCat TCP/UDP Source
采集指定端口(tcp、udp)的数据,可以读取流经端口的每一行数据
-
Spooling Directory Source
采集文件夹里新增的文件
-
Kafka Source(常用)
从Kafka消息队列中采集数据
2.2、Channel
接收Source发出的数据,可以把Channel理解为一个临时存储数据的管道。Channel类型有很多:内存、文件、内存+文件、Jdbc等。
Channel类型分类:
-
Memory Channel
使用内存作为数据的存储
优点:
- 效率高。因为不涉及磁盘IO
缺点:
- 可能会丢数据,如果Flume的agent宕机了,那么Channel中的数据就丢失了
- 内存是有限的,会存在内存不够用的情况
-
File Channel(最常用)
使用文件作为数据的存储
优点:
- 数据不会丢失
缺点:
- 效率相对内存来说优点慢,但是这个慢也不是特别慢
-
Spilable Memory Channel
使用内存和文件作为数据存储,先把数据存到内存中,如果内存中数据达到阀值再Flush到文件中
优点:
- 解决了内存不够的问题
缺点:
- 还是存在丢失数据的风险
2.3、Sink
从Channel中读取数据并存储到指定目的地。Sink的表现形式有很多:打印到控制台、HDFS、Kafka等。Channel的数据直到进入目的地才会删除,当Sink写入目的地失败后,可以自动重写,不会造成数据丢失,这块是有一个事务保证的。
常用的sink组件
-
Logger Sink
将数据作为日志处理,可以选择打印到控制台或者写到文件中,这个主要在测试的时候使用
-
HDFS Sink
将数据传输到HDFS中,这个是比较常见的,主要针对离线计算的场景
-
Kafka Sink
将数据发送到Kafka消息队列中,这个是比较常见的,主要针对实时计算场景,数据不落盘,实时传输,最后使用实时计算框架直接处理。
三、安装Flume
官方网站:flume.apache.org/
3.1、安装配置
-
下载安装包上传到linux机器上
-
解压flume安装包
tar -zxvf apache-flume-1.10.1-bin.tar.gz
-
修改flume的env环境变量配置文件
在flume的conf目录下,修改flume-env.sh.template的名称,去掉后缀template
mv flume-env.sh.template flume-env.sh
-
这样可以安装好了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
总体步骤:
- 定义每个组件的名称
- 配置每个组件的参数
- 串起来每个组件
4.1、实战
-
在flume的conf目录创建一个配置文件
vi demo.conf
把上面的配置复制进去这个文件
-
修改flume的Jdk路径
echo $JAVA_HOME
在flume-env.sh修改
export JAVA_HOME=/root/software/jdk1.8.0_341
-
配置log4j2的日志路径
在flume目录下面创建logs目录
修改conf目录下的log4j2.xml的property属性
/root/software/apache-flume-1.10.1-bin/logs
-
启动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的名字
-
测试
-
安装telnet
yum install -y telnet
-
连接flume
telnet localhost 44444
-
-
查看日志
五、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
-
创建目录
mkdir -p /root/log/demoDir
-
创建测试数据
vi demo.dat
zhangsan 18 m lisi 20 m hanmeimei f
-
到flume的conf目录下,创建file-to-hdfs.conf
vi file-to-hdfs.conf
-
启动hdfs
-
启动flume
bin/flume-ng agent -c conf -f conf/file-to-hdfs.conf -n a1
-
这时候报错,因为本机安装的没有Hadoop环境,所以我们把这个flume拷贝到hadoop环境机器上
scp -rq apache-flume-1.10.1-bin 192.168.234.100:/root/software/
-
校验
此时发现demo.dat已经变成了demo.dat.COMPLETE
-
查看hdfs内容
此时文件是.tmp后缀名的。此时没办法查看。两个解决方案:
-
停止Flume Agent
停止Agent就会去掉了.tmp的标志。每次停止之前就会把所有的文件解除占用状态,下次启动的时候如果有新数据,则产生新的文件,这个其实模拟了一下自动切文件之后的效果
-
等待配置的1小时后
查看文件内容
hdfs dfs -cat /flume/demoDir/demo-.1663503765932
-
-
如果想要生成的文件名有一个后缀是.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
代理用户