一、Flume概述
1.1、Flume定义
Flume是Cloudera(Hadoop的三大发型版本之一公司)提供的一个高可用,高可靠的分布式的海量日志采集、聚合和传输系统。Flume基于流式架构,灵活简单
为什么使用Flume
我们Java后台的日志数据需要使用大数据工具来进行实时分析处理时候,就需要通过Flume来进行流式采集,交给大数据服务器进行分析计算。解决的就是这个实时问题!
如果对实时性要求不高的场景也可以选择每天定时上传日志文件到HDFS上,也就用不到Flume。
Flume的主要作用:实时读取服务器本地磁盘的数据,并将数据写入到HDFS!
1.2、Flume基础架构
Flume在服务器运行时,是一个JVM进程(Agent),运行在JVM虚拟机上。以事件(Event)的形式将数据从源头传输到目的地。
三大组件
-
Source:对接外部用于采集日志数据
-
Channel:作为缓冲区调节Source读取和Sink写出
-
Sink:对接外部用于写出数据
以上三个组件在特殊的开发环境下支持自定义!!
Event
是Flume在传输数据的传输单元,以Event的形式将数据从源头传输到目的地。
由两部分构成:
- Header存放该event的一些属性(KV结构)
- Body存放传输的数据内容(字节数组)
结构有点类似网络信息传输的包。
二、Flume快速入门
Flume全版本下载地址当前最新版本为1.9.0,本次我们学习使用1.7.0版本!
2.1、安装Flume部署
-
将压缩包放入/opt/software目录下
-
解压到/opt/module目录中
tar -zxvf /opt/software/apache-hive-1.7.0 -C /opt/module/
-
将其目录下conf/目录中flume-env.sh.template改名为flume-env.sh,并进行以下配置
export JAVA_HOME=/opt/module/jdk1.8.0_251
2.2、入门案例
2.2.1、监控端口数据(官方案例)
案例需求:
使用Flume监听端口(NetCat Source),将端口中传输过来的数据 输出到控制台(Logger Sink)。
步骤实现
-
安装netcat工具
sudo yum install -y nc
netcat的基本使用
-
使用
nc -lk port
开启对端口xxx的持续监听(-lk:listen,keep open)(服务端) -
在另一台主机上使用
nc hostname port
与对应主机上的端口建立连接(客户端) -
然后客户端和服务端就可以相互通信了!!
-
一旦服务端停止,客户端相继断开。
-
-
判断44444端口是否被占用
sudo netstat -tunlp | grep 44444
-
创建Flume-Agent配置文件
flume-netcat-logger.conf
在flume的根目录下创建job文件夹,在job文件夹中创建此配置文件。并添加一下内容(官方的配置文件):
# Name the components on this agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = netcat a1.sources.r1.bind = localhost a1.sources.r1.port = 44444 # Describe the sink a1.sinks.k1.type = logger # Use a channel which buffers events in memory a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 # Bind the source and sink to the channel a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
我们先来解读一下这个配置文件做了些什么=>
# 第一部分:为名为a1的agent进行组件命名 sources:r1, sinks:k1, channels:c1 > 发现组件后都有一个s,可以看出在一个Agent中是可以同时存在多个source、channel、sink的 # 第二部分:配置source相关信息 r1.type: 名为r1的source通过netcat采集获取数据(监听端口) r1.bind: 监听端口的主机名 r1.port: 监听的端口号 # 第三部分:配置sink k1.type: 名为k1的sink通过logger来输出数据(控制台输出) # 第四部分:配置channel c1.type: 名为c1的channel使用memory作为缓冲区(内存缓冲) c1.capacity: channel的事件(event)容量 c1.trancactionCapacity: 传输事务的最大事件(event)容量 # 第五部分:source、sink和channel对接配置 a1.sources.r1.channels a1.sinks.k1.channel > source配置项是channels,而sink配置项是channel。下面有图可以查看 > 这就说明channel是可以接受来自多个source的信息的,一个source的信息也可以写到多个channel中 > channel的数据也可以供多个sink获取数据写出,**而每个sink只能从一个channel中获取数据写出**
以下是官方文档中给出的
NetCat Source
的配置清单:可对应第二部分的source配置,其他更多参照官方文档以下是官方文档给出的
logger sink
的配置清单:对应第三部分sink配置channel也不例外,官方文档也有对应的配置清单
-
启动一个Flume-Agent
bin/flume-ng agent --conf conf --conf-file job/netcat-flume-logger.conf --name a1 -Dflume.root.logger=INFO,console
--conf/-c
基本配置文件目录--conf-file/-f
配置文件名--name/-n
agent的名字-Dflume.root.logger=INFO,console
将所有INFO日志消息输出到控制台(附加配置)
或者使用
bin/flume-ng agent -c conf/ -f job/netcat-flume-logger.conf -n a1 -Dflume.root.logger=INFO,console
-
使用netcat进行连接
启动agent之后,运行flume进程的主机就相当一个netcat的服务端!我们之前的主机名写的是localhost,所以我们连接也只能在本地上连接
nc localhost 44444
,如果要跨主机连接,可以将配置文件中bind主机名改为hadoop102 -
测试发送信息
可以看到Flume控制台输出的内容确实是以Event为单位,分为headers和body两大部分!!
2.2.2、实时监控单个追加文件
案例需求:
实时监控hive的日志文件(/opt/module/hive-1.2.2/logs/hive.log)
- exec source
- memory channel
- logger sink
实现步骤
-
配置文件
file-flume-logger.conf
除了第二部分的source配置需要查看官方文档的配置清单,其他可以完全照抄
# Name the components on this agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = exec a1.sources.r1.command = tail -F /opt/module/hive-1.2.2/logs/hive.log # Describe the sink a1.sinks.k1.type = logger # Use a channel which buffers events in memory a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 # Bind the source and sink to the channel a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
官方给出的exec source配置清单:
官方示例:
a1.sources = r1 a1.channels = c1 a1.sources.r1.type = exec a1.sources.r1.command = tail -F /var/log/secure a1.sources.r1.channels = c1
tail
命令官方的推荐使用-F
而非-f
两者的区别在于,使用-F时,当文件发生变化导致监控失败,会自动进行尝试重新监控。
-
启动flume-agent,开始监控hive.log
bin/flume-ng agent -c conf/ -f job/file-flume-logger.conf -n a1 -Dflume.root.logger=INFO,console
-
启动hive,执行查询,观察flume的控制台输出情况
首先会读取日志文件的末尾10行,输出到控制台。
监控成功!!
2.2.3、监控文件 升级版
将控制台的输出内容转移输出到HDFS上!
- HDFS sink
准备工作
将以下jar包导入到flume的lib目录下:(这里的Hadoop相关Jar包最好与Hadoop环境版本相同)
配置项解读
查看官方给出的配置清单,HDFS sink在生产环境中使用的频率还是比较高的!
除了默认黑体的必须配置以外,以上圈出的都是常用的HDFS sink的配置
来看一个官方给出的配置示例:
HDFS sink的别名大全:
来对这些常用的配置项做一下详细的解读:
-
文件前、后缀
filePrefix
fileSuffix
在向HDFS写入文件的时候,自定义文件的前后缀,可以使用别名。例如
a1.sinks.k1.hdfs.filePrefix=%t a1.sinks.k1.hdfs.fileSuffix=.log
-
roll文件滚动
在向HDFS中写入的数据的时候,总不能只向一个文件中写入的吧,当达到一定条件时,需要强制滚动文件(切换到一个新文件),这样=利于数据的分离,避免文件太大影响效率。但是如果配置不当又会导致大量的小文件产生!!
rollInterval
: 文件滚动之间的时间间隔(默认30s)rollSize
: 滚动前,文件大小上限(默认1024kb)rollCount
:滚动前 写入事件的最大次数(默认10)
以上三个配置项,只要满足其一就会进行一次文件滚动!!**三个配置项都可以配置为0,代表不作为判断项。**例如:
# 每60s滚动一次 a1.sinks.k1.hdfs.rollInterval=60 # 文件大小达到128×1024×1024=134217728 实际配置时尽量比这个小!保证一个文件能存放到一个块中 a1.sinks.k1.hdfs.rollSize=134217700 # rollCount不作为判断项,无论多少的Event都不影响 a1.sinks.k1.hdfs.rollCount=0
可以看到当前的环境下其实使用默认的配置中很容易产生小文件,所以根据业务需求适当配置!!
-
批处理写入文件
batchSize
: 当Event数量达到一定值,flush写入到HDFS中。(默认100)其实到达一定时间也会被强制刷新写入到HDFS
-
文件存储格式和编码解码器
-
codeC
:编/解码器(可选:gzip, bzip2, lzo, lzop, snappy)仅当文件格式(fileType)是CompressedStream时配置!! -
fileType
: 文件存储格式(默认SequenceFile,可选:SequenceFile
orDataStream
orCompressedStream
)
-
-
文件夹滚动
除了之前说的文件需要不断滚动,当我们需要配合使用Hive的分区表的时候,我们也希望定时切换文件夹,例如每天一个文件夹,文件夹下每个小时又分一个文件夹。==如果要使用此功能,必要配置中hdfs.path就不能写死而是使用别名!==否则滚来滚去都是这个文件夹没有效果!!
round
: 是否开启文件夹滚动(默认为false)需要设置为true才能生效roundValue
:滚动的间隔单元(Unit)数(默认1,每过一个Unit滚动一次)roundUnit
:滚动的间隔单元单位(默认second,可选:second
,minute
orhour
.)
-
使用本地时间戳
useLocalTimeStamp
(默认false,使用header中的时间戳),由于我们现在的header中什么都没有,如果不设置为true
,那么所有与时间相关的都不会生效。
实现步骤
-
Flume配置文件
file-flume-hdfs.conf
# Name the components on this agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = exec a1.sources.r1.command = tail -F /opt/module/hive-1.2.2/logs/hive.log # Describe the sink a1.sinks.k1.type = hdfs a1.sinks.k1.hdfs.path=hdfs://hadoop102:9000/flume/%Y%m%d/%H # 文件前缀 a1.sinks.k1.hdfs.filePrefix=log- # 文件夹滚动 a1.sinks.k1.hdfs.round=true a1.sinks.k1.hdfs.roundValue=1 a1.sinks.k1.hdfs.roundUnit=hour # 使用本地时间戳 a1.sinks.k1.hdfs.useLocalTimeStamp=true # 批处理最大数量 a1.sinks.k1.hdfs.batchSize=1000 # 文件存储类型 a1.sinks.k1.hdfs.fileType=DataStream # 文件滚动 a1.sinks.k1.hdfs.rollInterval=60 a1.sinks.k1.hdfs.rollSize=134217700 a1.sinks.k1.hdfs.rollCount=0 # Use a channel which buffers events in memory a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 # Bind the source and sink to the channel a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
-
启动开始监控
bin/flume-ng agent -n a1 -c conf/ -f job/file-flume-hdfs.conf
每当日志变化时,在文件滚动的间隔时间内,所有的事件都会被 传输写入到临时文件(.tmp)中!文件滚动时间到达且有新的Event过来就会重新创建文件,之前的临时文件变为持久性文件!如果只是到了滚动时间,而没有Event过来是不会创建文件的!
2.2.4、监控文件夹变化
案例需求
实时监控一个文件夹下的文件添加,并实时同步到HDFS上。
- Spooling Directory Source
- HDFS sink
Spooling Directory Source配置清单
-
基本配置
spoolDir
写明要监控的文件夹,只能监控文件的个数的增加,但是并不能监测到文件内容的变化!!
-
fileSuffix
:完成同步后添加的文件后缀当被监控的目录下的文件被同步到了HDFS上时,会为本地文件系统中的文件加上后缀(默认
.COMPLETED
) -
includePattern
,ignorePattern
文件‘黑白名单’使用正则表达式,设置哪些文件同步,哪些不同步。
实现步骤
-
创建一个文件夹用于监控(/opt/module/flume-1.7.0/upload)
-
配置文件
spooldir-flume-hdfs.conf
修改2.2.3、的配置文件中source部分即可:
a1.sources.r1.type = spooldir a1.sources.r1.spoolDir = /opt/module/flume-1.7.0/upload/
-
启动
bin/flume-ng agent -n a1 -c conf/ -f job/spooldir-flume-hdfs.conf
-
测试
启动时upload文件夹下什么都没有,所以HDFS上也没有输出文件。
-
创建文件test.txt 拷贝到 upload/
HDFS上出现输出文件,大小和test.txt内容一样! upload/文件夹中的test.txt被加上了COMPLETED后缀! -
测试直接在upload/下创建文件
也可以正常同步到。但是当同步过后,继续修改文件是同步不到修改的内容的!!!
-
尝试重复添加同一文件
文件内容被成功上传!!但是文件名并没有被修改,查看flume日志,出现报错
-
尝试添加.COMPLETED后缀的文件
HDFS上并没有同步到!!!
-
-
增加配置再次测试
# 不同步xx.tmp文件 a1.sources.r1.ignorePattern=([^ ]*\.tmp)
果然test4.tmp就没有被同步到!!
测试总结
- 上传的文件,同步输出到HDFS上,只同步文件内容!!
- 对已上传同步的文件进行修改,修改的内容无法被同步监测到!!
- 不要多次上传同一文件,会导致文件内容同步成功,但是在修改文件名的时候失败!
fileSuffix
==尽量选择未使用的后缀,==否则会导致无法被监控到!
2.2.5、断点续传——实时监控目录文件追加修改
案例需求
监控一个或者多个的文件修改,并且支持断点续传
- Taildir source
Exec Source监控文件变化存在的问题:
-
不支持断点续传
如果生产环境中,Flume挂掉,再次启动的时候只能传输最后10行的数据!!
-
正常情况下有数据重复
每次启动都要将文件的最后10行传输,可能存在数据的重复。
-
使用 -c +0每次从文件头扫描监控
可以解决生产时挂掉导致大部分数据丢失的问题,但是平时使用数据重复率飙升!
-
只能监控一个文件
这几个问题就决定了ExecSource不适合用来做文件内容追加修改监控
而使用TailDir,使用了一个positionFile记录上一次传输的位置,即使挂掉,中间的文件修改在重启之后也会被正确传输!
而且可以同时监控多个文件!!
TaildirSource配置清单