Flume处在大数据框架中的数据传输层,主要解决数据从其他服务器传输到大数据集群的问题
Flume
是Cloudera
提供的一个高可用、高可靠、分布式的海量日志采集、聚合和传输的系统。Flume
基于流式框架,灵活简单。目前移交给Apache
维护——Flume官网。
官网明确说了Flume
的工作对象是log data
,所有不能传输视频、图片等二进制文件。Flume
在生产环境中的数据更多来源于java后台日志数据或者爬虫数据,它们大多是在本地文件系统且一般是动态添加实时增加,为了解决日志文件的保存,在没有Flume
时可以等一天时间结束通过定时任务将日志文件-put
进hdfs
也是可以的,但是hdfs
缺乏实时性,日志文件所包含的信息价值已经失效了。因此Flume
可以将后台日志文件实时传输到hdfs
,且Flume
不仅可以实时传输服务器本地磁盘文件夹还可以传输网络端口传输来的数据。
Flume
最主要的作用就是实时读取服务器本地磁盘的数据,将数据写到HDFS
中
首先看到的是Agent
,它是一个JVM
进程,在这个进程中有三大组件:Source
、Channel
、Sink
。第一个叫Source
源头,接入的是Web Server
可以做一些轻量的数据处理,可以说它就是和外界打交道用来读取数据的地方,读取的数据将传到Channel
管道,起到一定的缓冲作用减少各组件的压力。最终传输到Sink
它本身是一个城槽,它是将数据写出去的组件,这些原理在Flume
图标体现的淋漓尽致。
Agent
是一个JVM
进程,它以事件的形式将数据从源头送至目的。
Agent
主要有 3 个部分组成,Source
、Channel
、Sink
。
Source
是负责接收数据到Flume Agent
的组件。Source
组件可以处理各种类型、各种
格式的日志数据,包括 avro
、thrift
、exec
、jms
、spooling directory
、netcat
、sequence
generator
、syslog
、http
、legacy
。这些组件太多可以参考一下官方文档
Sink
不断地轮询 Channel 中的事件且批量地移除它们,并将这些事件批量写入到存储
或索引系统、或者被发送到另一个 Flume Agent。
Sink
组件目的地包括 hdfs
、logger
、avro
、thrift
、ipc
、file
、HBase
、solr
、自定 义
。
Channel
是位于Source
和 Sink
之间的缓冲区。因此,Channel 允许 Source
和Sink
运
作在不同的速率上。Channel
是线程安全的,可以同时处理几个Source
的写入操作和几个
Sink
的读取操作。
Flume
自带两种 Channel
:Memory Channel
和 File Channel
以及Kafka Channel
。
Memory Channel
是内存中的队列。Memory Channel
在不需要关心数据丢失的情景下适
用。如果需要关心数据丢失,那么Memory Channel
就不应该使用,因为程序死亡、机器宕
机或者重启都会导致数据丢失。
File Channel
将所有事件写到磁盘。因此在程序关闭或机器宕机的情况下不会丢失数
据。
传输单元,Flume
数据传输的基本单元,以Event
的形式将数据从源头送至目的地。
Event
由Header
和Body
两部分组成,Header
用来存放该event
的一些属性,为K-V
结构,
Body
用来存放该条数据,形式为字节数组。
解压
tar -zxvf apache-flume-1.9.0-bin.tar.gz
配置flume-env.sh
文件
cd flume-1.9.0/conf/
mv flume-env.sh.template flume-env.sh
vim flume-env.sh
当有具体的任务从哪里读最终写到哪里,只需要修改配置文件后启动Agent
即可,Flume
是一个分布式的框架,但是并不用向HDFS
那样分发脚本配置文件等,那么它的分布式怎么来的?从前面看到avor source
和avor sink
组件,这两个组件可以串行使用avor sink
把数据写到avor source
并且传输到avor sink
,即将Flume
安装到多台服务器从而形成了分布式,而不是在搭建的时候就是分布式。不需要启什么进程,当具体的任务来了我们再开启具体的任务就OK了。
使用Flume
监听一个端口,收集该端口数据,并打印到控制台。
下面开始选取Source
和Sink
该用什么组件,首先监听的是端口可以选用netcat
,打印到控制台则选用logger
,中间的Channel
选取内存型或者磁盘型的都可以。
通过netcat
工具向本机4444
端口发送数据,通过Flume
监控4444
端口
nc
测试master
开启本地4444
端口服务
[root@master job]# nc -l 4444
解释:
nc
即netcat
-lk
永久监听 -l
临时监听4444
端口号相当于开启了一个服务,需要首先开启服务,否在其他节点监听该端口时会拒绝连接
slave01
开启监听,即启动客户端
[root@slave01 ~]# nc master 4444
Flume
实现这个案例来自Flume
官方案例,根据官方提供的配置文件结合案例需求如下
# 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 = master
a1.sources.r1.port = 4444
# 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
Flume
的使用无非就是选取合适的Agent
的三大组件,通过配置文件选取合适的组件,如上面的配置文件分为五部分
第一部分:Name the components on this agent
给这个Agent
取名为a1
主要区分同一个节点开启多个Flume
情况,分别给source
取名为r1
、channels
取名为c1
、sink
取名为k1
,注意配置文件的单复数,可以得出三个组件都是可以选取多个。
第二部分 Describe/configure the source
source
选取netcat
组件,监听master:4444
第三部分 Describe the sink
sink
选取logger
组件
第四部分 Use a channel which buffers events in memory
channel
选取内存性,设置缓存大小为1000
个事件(Event),一次传输100
个事务,配置是要注意transactionCapacity
要小于capacity
。
第五部分 Bind the source and sink to the channel
将source
、sink
与channel
进行绑定,注意配置文件中单词的单复数,注意一个sink
只能绑定一个channel
,如下图:
在Flume
工程目录下新建job
文件夹,将上述配置文件命名为netcat_flume_logger.conf
放入其中统一管理,根据官方给出的命令
$ bin/flume-ng agent --conf conf --conf-file example.conf --name a1 -Dflume.root.logger=INFO,console
结合实际情况启动本次任务
flume-ng agent --conf /usr/local/soft/flume-1.9.0/conf/ --conf-file /usr/local/soft/flume-1.9.0/job/netcat-flume-logger.conf --name a1 -Dflume.root.logger=INFO,console
结果如下
启动成功开始测试,向master:4444
发送数据
实时监测Hadoop
日志文件hadoop-root-namenode-master.log
,并上传至HDFS
中
在写入hdfs
之前先打印到控制台上用于测试,参照2.3.1
的配置文件修改。在Linux
中监测文件的追入需要使用tail -f/F
命令,参考官方文档得知需要使用Exec Source
组件,官方给出的配置文件如下
黑色加粗为必配选项级连接到channel
选择type
为exec
,command
为需要执行的Linux
命令,通过该命令返回的数据作为数据源,因此结合案例在job
文件夹下新建配置文件file_flume_logger.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 /usr/local/soft/hadoop-2.7.2/logs/hadoop-root-namenode-master.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
启动flume
任务
flume-ng agent --conf /usr/local/soft/flume-1.9.0/conf/ --conf-file /usr/local/soft/flume-1.9.0/job/file-flume-logger.conf --name a1 -Dflume.root.logger=INFO,console
首先会读取hadoop-root-namenode-master.log
最后十行数据再开启监测
启动hdfs
观察窗口变化情况
start-dfs.sh
由于控制台的输入有限不能完全显示日志的变化情况,但从现象看出文件是可以监测,下面将sink
的logger
组件替换成可以将其写入hdfs
的组件HDFS Sink
,从官方给出的文档整理如下
Name | Default | Description |
---|---|---|
channel | – | |
tpye | – | The component type name, needs to be hdfs |
hdfs.path | – | HDFS directory path (eg hdfs://namenode/flume/webdata/) |
Name | Default | Description |
---|---|---|
hdfs.filePrefix | FlumeData | 文件前缀 |
hdfs.fileSuffix | – | 文件后缀 |
hdfs.rollInterval | 30 | 30秒滚动一次 |
hdfs.rollSize | 1024 | 文件达到1024byte 滚动一次 |
hdfs.rollCount | 10 | 十个事件滚动一次 |
hdfs.round | false | 下面两个配置参数的开关,文件夹的滚动 |
hdfs.roundValue | 1 | 根据下面配置时间滚动文件夹 |
hdfs.roundUnit | second | 可配置时、分、秒 |
hdfs.useLocalTimeStamp | false | 是否使用本地时间 |
hdfs.path
写入hdfs
的路径,一般不会写死,搭配hdfs.round
可实现动态创建文件夹方便查看;hdfs.filePrefix
、hdfs.fileSuffix
了解即可使用默认;hdfs.rollInterval
默认30秒滚动一次即创建一个文件,生产环境一定要配置为0
,不使用这个功能因为很少有公司能达到这个数量级的日志,半分钟达到128M
的日志级别,否则会产生很多小文件不利于hdfs管理;hdfs.rollSize
按照文件大小进行滚动,结合hdfs
的block
块大小进行配置,一般略小于块大小最优防止一个事件没有完成文件被hdfs
分块了,如block
块大小配置为128M
则hdfs.rollSize
配置为134217000
;hdfs.rollCount
按事件进行滚动,这个配置需要根据具体的事件情况,需要提交估计每次事件的数据量进行配置;hdfs.round
滚动文件夹的开关,根据hdfs.roundValue
,hdfs.roundUnit
的数值进行动态创建文件夹,默认一秒钟创建一个文件夹…这个有点不现实,一般是一个小时滚动一次创建一个文件夹,配合动态的hdfs.path
可以实现按时间进行归档方便管理。注意:一旦开启按时间进行滚动一定要使用本队时间即将hdfs.useLocalTimeStamp
配置为true
。
# 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 /usr/local/soft/hadoop-2.7.2/logs/hadoop-root-namenode-master.log
# Describe the sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://master:9000/flume/%Y%m%d/%H
# 上传文件的前缀
a1.sinks.k1.hdfs.filePrefix = logs
# 是否按照时间滚动文件夹
a1.sinks.k1.hdfs.round = true
# 多少时间单位创建一个新的文件夹
a1.sinks.k1.hdfs.roundValue = 1
# 重新定义时间单位
a1.sinks.k1.hdfs.roundUnit = hour
# 是否使用本地时间戳
a1.sinks.k1.hdfs.useLocalTimeStamp = true
# 积攒多少个 Event 才 flush 到 HDFS 一次
a1.sinks.k1.hdfs.batchSize = 100
# 设置文件类型,可支持压缩
a1.sinks.k1.hdfs.fileType = DataStream
# 多久生成一个新的文件
a1.sinks.k1.hdfs.rollInterval = 30
# 设置每个文件的滚动大小
a1.sinks.k1.hdfs.rollSize = 134217700
# 文件的滚动与 Event 数量无关
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
启动Flume
任务
flume-ng agent --conf /usr/local/soft/flume-1.9.0/conf/ --conf-file /usr/local/soft/flume-1.9.0/job/file-flume-hdfs.conf --name a1
解释a1.sinks.k1.hdfs.path = hdfs://master:9000/flume/%Y%m%d/%H
:动态创建文件夹按照其时间每小时创建一个文件夹方便管理。
因为Flume
需要将数据写进hdfs
中,因此需要相关jar包,可以先启动任务让其报错,通过错误信息将对应的jar包放进.../flume/lib
中,因hadoop
版本而异,我的版本是2.7.2
需要的jar包如下:
commons-configuration-1.6.jar
commons-io-2.4.jar
hadoop-auth-2.7.2.jar
hadoop-common-2.7.2.jar
hadoop-hdfs-2.7.2.jar
htrace-core-3.1.0-incubating.jar
再次启动flume
任务同时启动hdfs
,通过mater:50070
观察现象,若没有flume
文件,可以在hdfs
上敲几个命令让其产生新的日志文件。
为了方便测试配置了30秒滚动一次文件,生产环境请设置为0。看一下写进hdfs
的日志文件[忽略上面马赛克,听歌才有思路]
先发,随后补充