Flume
1、Flume简介
1.1、 Flume概述
Flume是一个分布式、可靠、和高可用的海量日志聚合的系统,支持在系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。
Flume 初始的发行版本目前被统称为 Flume OG(original generation),属于 cloudera。但随着 Flume 功能的扩展,Flume OG 代码工程臃肿、核心组件设计不合理、核心配置不标准等缺点暴露出 来,尤其是在 Flume OG 的最后一个发行版本 0.94.0 中,日志传输不稳定的现象尤为严重。为了解决这 些问题,2011 年 10 月 22 号,cloudera 完成了 Flume-728,对 Flume 进行了里程碑式的改动:重构 核心组件、核心配置以及代码架构,重构后的版本统称为 Flume NG(next generation)
1.2、Flume使用场景
线上数据一般主要是落地(存储到磁盘)或者通过socket传输给另外一个系统,这种情况下,你很难推动线上应用或服务去修改接口,实现直接向kafka里写数据,这时候你可能就需要flume这样的系统帮你 去做传输。
1.3、 Flume优点
实践证明,Flume有着下面的优点:
- 当收集数据的速度超过将写入数据的时候,也就是当收集信息遇到峰值时,这时候收集的信息非常 大,甚至超过了系统的写入数据能力,这时候,Flume会在数据生产者和数据收容器间做出调整, 保证其能够在两者之间提供平稳的数据。
- Flume的管道是基于事务,保证了数据在传送和接收时的一致性.
- Flume是可靠的,容错性高的,可升级的,易管理的,并且可定制的(可以根据生产需要自行定义 一个数据来源端或者终点端)。
- 除了日志信息,Flume同时也可以用来接入收集规模宏大的社交网络节点事件数据,比如 Facebook、Twitter、电商网站如亚马逊等。
- 支持多路径流量,多管道接入流量,多管道接出流量,上下文路由等。
2、 Flume的体系架构
2.1、Flume架构
比较核心的组件
- Client:Client生产数据,运行在一个独立的线程。
- Event: 一个数据单元,消息头和消息体组成。(Events可以是日志记录、 avro 对象等。)
- Flow: Event从源点到达目的点的迁移的抽象。
- Agent: 一个独立的Flume进程,包含组件Source、 Channel、 Sink。(Agent使用JVM 运行Flume。每台机器运行一个agent,但是可以在一个agent中包含多个sources和sinks。)
- Source: 数据收集组件。(source从Client收集数据,传递给Channel)
- Channel: 中转Event的一个临时存储,保存由Source组件传递过来的Event。(Channel连 接 sources 和 sinks ,这个有点像一个队列。)
- Sink: 从Channel中读取并移除Event, 将Event传递到持久点存储或下一个Agent(如 果有的话(Sink从Channel收集数据,运行在一个独立线程。)
组件 | 中文名 | 作用 |
---|---|---|
client | 客户端 | Client生产数据 ,运行在一个独立的线程中 |
event | 事件 | 消息头和消息体组成。(Event可以是日志记录、avro对象等。) |
flow | 流 | Event从源点到达目的点的迁移的抽象。 |
agent | 代理 | 运行在JVM中,包含组件Source、Channel、Sink。每台机器运行一个agent,但是一个agent中可以包含多个sources和sinks。 |
source | 源 | sources从client收集数据,传递给Channel |
channel | 通道 | 负责接受source端的数据,然后将数据推送到sink端 |
sink | 存储 | 负责从channel端拉取数据 ,并将其推送到持久化系统或者是下个Agent |
selector | 选择器 | 作用于source端,然后决定数据发往那个目标 |
interceptor | 拦截器 | flume允许使用拦截器拦截数据。允许使用拦截器链,作用于source和sink阶段。 |
- Flume的采集的大致流程
2.2、Flume的组件详解
2.2.1. Agent结构
Flume 运行的核心是 Agent。Flume以agent为最小的独立运行单位。一个agent就是一个JVM。它 是一个完整的数据收集工具,含有三个核心组件,分别是 source、 channel、 sink。
通过这些组件, Event 可以从一个地方流向另一个地方,如下图所示。
2.2.2. source
- (数据输入的方式,以及数据输入的方式<参数>)
source是数据的收集端,负责将数据捕获后进行特殊的格式化,将数据封装到事件(event) 里,然后将事件推入Channel中。 Flume提供了很多内置的Source, 支持 Avro, log4j, syslog 和 http post(body为json格式)。可以让应用程序同已有的Source直接打交道,如AvroSource, SyslogTcpSource。 如果内置的Source无法满足需要, Flume还支持自定义Source。
举例几个比较常用的:
- NetCat Source:绑定的端口(tcp、udp),将流经端口的每一个文本行数据作为Event输入
- type:source的类型,必须是netcat。
- bind:要监听的(本机的)主机名或者ip。此监听不是过滤发送方。一台电脑不是说只有一 个IP。有多网卡的电脑,对应多个IP。
- port:绑定的本地的端口。
- Avro Source:监听一个avro服务端口,采集Avro数据序列化后的数据
- type:avrosource的类型,必须是avro。
- bind:要监听的(本机的)主机名或者ip。此监听不是过滤发送方。一台电脑不是说只有一 个IP。有多网卡的电脑,对应多个IP。
- port:绑定的本地的端口。
- Exec Source:于Unix的command在标准输出上采集数据;
- type:source的类型:必须是exec。
- command:要执行命令。
- Spooling Directory Source:监听一个文件夹里的文件的新增,如果有则采集作为source。
- type:source 的类型:必须是spooldir
- spoolDir:监听的文件夹 【提前创建目录】
- fileSuffix:上传完毕后文件的重命名后缀,默认为.COMPLETE
- deletePolicy:上传后的文件的删除策略never和immediate,默认为never。
- fileHeader:是否要加上该文件的绝对路径在header里,默认是false。
- basenameHeader:是否要加上该文件的名称在header里,默认是false。
2.2.3. channel
- (用来缓存source递过来的数据,并形成一个个event时间,等待sink来拿)
Channel是连接Source和Sink的组件,大家可以将它看做一个数据的缓冲区(数据队列),它可以 将事件暂存到内存中也可以持久化到本地磁盘上, 直到Sink处理完该事件。介绍两个较为常用的 Channel, MemoryChannel和FileChannel。
举例几个比较常用的:
- Memory Channel使用内存作为数据的存储。
- Type channel的类型:必须为memory
- capacity:channel中的最大event数目
- transactionCapacity:channel中允许事务的最大event数目
- File Channel 使用文件作为数据的存储
- Type channel的类型:必须为 file
- checkpointDir :检查点的数据存储目录【提前创建目录】
- dataDirs :数据的存储目录【提前创建目录】
- transactionCapacity:channel中允许事务的最大event数目
- Spillable Memory Channel 使用内存作为channel超过了阀值就存在文件中
- Type channel的类型:必须为SPILLABLEMEMORY
- memoryCapacity:内存的容量event数
- overflowCapacity:数据存到文件的event阀值数
- checkpointDir:检查点的数据存储目录
- dataDirs:数据的存储目录
2.2.4. sink
- (数据输出的方式,将channel整理好的一个个event,传送到指定地方)
Sink从Channel中取出事件,然后将数据发到别处,可以向文件系统、数据库、 hadoop存数据, 也可以是其他agent的Source。在日志数据较少时,可以将数据存储在文件系统中,并且设定一定 的时间间隔保存数据。
举例几个比较常用的:
- HDFS Sink:将数据传输到hdfs集群中。
- type:sink的类型 必须是hdfs。
- hdfs.path:hdfs的上传路径。
- hdfs.filePrefix:hdfs文件的前缀。默认是:FlumeData
- hdfs.rollInterval:间隔多久产生新文件,默认是:30(秒) 0表示不以时间间隔为准。
- hdfs.rollSize:文件到达多大再产生一个新文件,默认是:1024(bytes)0表示不以文件 大小为准。
- hdfs.rollCount:event达到多大再产生一个新文件,默认是:10(个)0表示不以event 数目为准。
- hdfs.batchSize:每次往hdfs里提交多少个event,默认为100
- hdfs.fileType:hdfs文件的格式主要包括:SequenceFile, DataStream ,CompressedStream,如果使用了CompressedStream就要设置压缩方式。
- hdfs.codeC:压缩方式:gzip, bzip2, lzo, lzop, snappy
- 注:%{host}可以使用header的key。以及%Y%m%d来表示时间,但关于时间的表示需 要在header里有timestamp这个key。
- Avro Sink:数据被转换成Avro Event,然后发送到指定的服务端口上。
- type:sink的类型:必须是 avro。
- hostname:指定发送数据的主机名或者ip
- port:指定发送数据的端口
- File Roll Sink:数据发送到本地文件。
- type:sink的类型:必须是 file_roll。
- sink.directory:存储文件的目录【提前创建目录】
- batchSize:一次发送多少个event。默认为100
- sink.rollInterval:多久产生一个新文件,默认为30s。单位是s。0为不产生新文件。 【即使没有数据也会产生文件】
2.2.5. Interceptor
当我们需要对数据进行过滤时,除了我们在Source、 Channel和Sink进行代码修改之外, Flume 为我们提供了拦截器,拦截器也是chain形式的。
拦截器的位置在Source和Channel之间,当我们为Source指定拦截器后,我们在拦截器中会 得到event,根据需求我们可以对event进行保留还是 抛弃,抛弃的数据不会进入Channel中。
- Timestamp Interceptor 时间戳拦截器; 在header里加入key为timestamp,value为当前时 间。
- type:拦截器的类型,必须为timestamp
- preserveExisting:如果此拦截器增加的key已经存在,如果这个值设置为true则保持原来的值,否则覆盖原来的值。默认为false
- Host Interceptor 主机名或者ip拦截器,在header里加入ip或者主机名
- type:拦截器的类型,必须为host
- preserveExisting:如果此拦截器增加的key已经存在,如果这个值设置为true则保持原 来的值,否则覆盖原来的值。默认为false
- useIP:如果设置为true则使用ip地址,否则使用主机名,默认为true
- hostHeader:使用的header的key名字,默认为host
- Static Interceptor 静态拦截器,是在header里加入固定的key和value。
- type:avrosource的类型,必须是static。
- preserveExisting:如果此拦截器增加的key已经存在,如果这个值设置为true则保持原来 的值,否则覆盖原来的值。默认为false
- key:静态拦截器添加的key的名字
- value:静态拦截器添加的key对应的value值
2.3、Flume特性
-
复杂流动
-
Flume允许用户构建多跳流程,其中事件在到达最终目的地之前会通过多个代理传播。它还允 许扇入和扇出流,上下文路由和备份路由(故障转移)
- 为了使数据跨多个代理或跃点流动,前一个代理的接收器和当前跃点的源必须为avro类型,接收器指向源的主机名(或IP地址)和端口
- 这可以在Flume中实现,方法是为多个第一层代理配置一个avro接收器,它们均指向单个代理的avro源(同样,在这种情况下,您可以使用节俭的源/接收器/客户端)。第二层代理上的此源将接收到的事件合并到一个通道中,该通道由接收器消耗到其最终目的 地。
- Flume支持将事件流复用到一个或多个目的地。这是通过定义一种流多路复用器来实现 的,该流多路复用器可以将事件复制或选择性地路由到一个或多个通道。
-
-
可靠
- 只有当sink接收到,数据落地完成的信息之后,才会将数据从通道中删除。 事件在每个代理上的一 个通道中上游。然后将事件传递到流中的下一个代理或终端存储库(如HDFS)。仅将事件存 储在下一个代理程序的通道或终端存储库中之后,才将其从通道中删除。这就是Flume中单跳 消息传递语义如何提供流的端到端可靠性的方式。
- 数据传输的方式不是byte,而是一个个的event。Flume使用事务性方法来确保事件的可靠传递。源和接收器分别在事务中封装存储在通道中或由通道提供的事务中提供的事件的存储/检索。 这确保了事件集在流中从点到点可靠地传递。在多跳流的情况下,来自上一跳的接收器和来自 下一跳的源均运行其事务,以确保将数据安全地存储在下一跳的通道中。
-
可恢复
- 当数据丢失了,只有从存储在磁盘的方式,才能将数据找回 事件在通道中上演,该通道管理从故障 中恢复。Flume支持持久的文件通道,该通道由本地文件系统支持。还有一个内存通道可以将 事件简单地存储在内存队列中,这虽然速度更快,但是当代理进程死亡时,仍保留在内存通道 中的任何事件都无法恢复。
2.4、Flume执行流程
-
执行流程图
-
-
1 Source 接受数据
-
2 Channel Processor 处理 Event
-
3 Channel Processor 将 Event 传递给 interceptor链对 Event 进行过滤操作
-
4 过滤完之后再把 Event 发送回 Channel Prodessor
-
5 Channel Processor把 Event 发送给Channel selectors
-
6 Channel selector返回Event 属于哪个Channel
-
7 根据第6步返回的结果,将Event发送到指定的Channel
-
8 SinkProcessor从Channel中拉去数据
-
9 最后把数据Sink出去
2.5、Flume事务
- 推送事务流程
- doPut: 把批数据写入到临时缓冲区putList
- doCommit: 检查Channel容量是否足够,如果容量足够则把putList里的数据发送到Channel
- doRollBack:如果Channel容量不够,则把数据回滚到putList
- 拉取事务流程
- doTake:把数据读取到临时缓冲区takeList
- doCommit:检查数据是否发送成功,成功的话,则把event从takeList中移除
- doRollBack:如何发送失败,则把takeList的数据回滚数据到Channel
3、Flume安装
Flume安装:
https://blog.csdn.net/weixin_43660536/article/details/118809169.
4、Flume使用
4.1. 案例1监控端口数据
http://flume.apache.org/FlumeUserGuide.html#a-simple-example
- 创建一个专门防止flume配置文件的目录
[root@node01 ~]# mkdir -p /opt/bdp/apache-flume-1.6.0-bin/options
- 创建配置文件
[root@node01 ~]# vim example.conf
## 新增以下内容
# example.conf: A single-node Flume configuration
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444
a1.sinks.k1.type = logger
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
- 启动flume
[root@node01 ~]# flume-ng agent -n a1 -c options/ -f example.conf -Dflume.root.logger=INFO,console
- 安装telnet
[root@node01 ~]# yum install telnet
- 向44444端口中输入数据
[root@node01 ~]# telnet localhost 44444
- 退出:在启动服务的窗口关闭
- ctrl + c
提示:Memory Chanel 配置
- capacity:默认该通道中最大的可以存储的event数量是100,
- trasactionCapacity:每次最大可以source中拿到或者送到sink中的event数量也是100 keep-
- alive:event添加到通道中或者移出的允许时间
- byte:即event的字节量的限制,只包括eventbody
4.2. 案例2 两个flume做集群
-
node01服务器中,配置文件
-
# Name the components on this agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 a1.sources.r1.type = exec a1.sources.r1.command = tail -F /opt/bdp/flume.txt a1.sinks.k1.type = avro a1.sinks.k1.hostname = node02 a1.sinks.k1.port = 45454 a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
-
-
node02服务器中,安装Flume(步骤略)
-
a2.sources = r1 a2.sinks = k1 a2.channels = c1 a2.sources.r1.type = avro a2.sources.r1.bind = node02 a2.sources.r1.port = 45454 a2.sinks.k1.type = logger a2.channels.c1.type = memory a2.channels.c1.capacity = 1000 a2.channels.c1.transactionCapacity = 100 a2.sources.r1.channels = c1 a2.sinks.k1.channel = c1
-
-
先启动node02的Flume
-
flume-ng agent -n a2 -c options/ -f example.conf -Dflume.root.logger=INFO,console
-
再启动node01的Flume
-
flume-ng agent -n a1 -c options/ -f example.conf2
打开telnet 测试 node02控制台输出结果
4.3. 案例3 Exec Source
-
http://flume.apache.org/FlumeUserGuide.html#exec-source 配置文件
-
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/bdp/flume.exec.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 -n a1 -c options/ -f example.conf -Dflume.root.logger=INFO,console
- 创建空文件演示 touch flume.exec.log,循环添加数据
for i in {1..50}; do echo "$i hi flume" >> flume.exec.log ; sleep 0.1; done
4.4. 案例4Spooling Source
-
http://flume.apache.org/FlumeUserGuide.html#exec-source 配置文件
-
a1.sources = r1 a1.sinks = k1 a1.channels = c1 a1.sinks.k1.type = logger a1.sources.r1.type = spooldir a1.sources.r1.spoolDir = /home/logs a1.sources.r1.fileHeader = true a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
-
启动Flume
flume-ng agent -n a1 -c options/ -f example.conf -Dflume.root.logger=INFO,console
- 拷贝文件演示
mkdir logs
cp flume.exec.log logs/
4.5. 案例5hdfs sink
- http://flume.apache.org/FlumeUserGuide.html#hdfs-sink 配置文件
a1.sources = r1
a1.sinks = k1
a1.channels = c1
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /home/logs
a1.sources.r1.fileHeader = true
a1.sinks.k1.type=hdfs
a1.sinks.k1.hdfs.path=hdfs://hdfs-bdp/flume/%Y-%m-%d/%H%M
##每隔60s或者文件大小超过10M的时候产生新文件
##hdfs有多少条消息时新建文件,0不基于消息个数
a1.sinks.k1.hdfs.rollCount=0
##hdfs创建多长时间新建文件,0不基于时间
a1.sinks.k1.hdfs.rollInterval=60
##hdfs多大时新建文件,0不基于文件大小
a1.sinks.k1.hdfs.rollSize=10240
##当目前被打开的临时文件在该参数指定的时间(秒)内,没有任何数据写入,则将该临时文件关闭并重命名
成目标文件
a1.sinks.k1.hdfs.idleTimeout=3
a1.sinks.k1.hdfs.fileType=DataStream
a1.sinks.k1.hdfs.useLocalTimeStamp=true
##每五分钟生成一个目录:
##是否启用时间上的”舍弃”,这里的”舍弃”,类似于”四舍五入”,后面再介绍。如果启用,则会影响除了%t
的其他所有时间表达式
a1.sinks.k1.hdfs.round=true
##时间上进行“舍弃”的值;
a1.sinks.k1.hdfs.roundValue=5
##时间上进行”舍弃”的单位,包含:second,minute,hour
a1.sinks.k1.hdfs.roundUnit=minute
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
- 创建HDFS目录
hadoop fs -mkdir /flume
- 启动Flume
flume-ng agent -n a1 -c options/ -f example.conf -Dflume.root.logger=INFO,console
- 查看hdfs文件
hadoop fs -ls /flume/*