深入学习Apache Flume核心架构及原理
Apache Flume是什么?
Apache Flume是cloudera公司开源的分布式海量日志聚合系统,可用于在系统中从多种不同数据源收集,聚合,传输大量日志数据到数据集中存储地。作为一款流式日志采集工具,flume提供对数据进行简单处理并写到各种数据接收方(可定制)的能力。
一.Apache Flume组件概念
1.1 Flume完整架构图:
Event: flume传输数据最基本的单元,由消息头和消息体组成;
Interceptor:拦截器,主要作用是将采集到的数据根据用户的配置进行过滤和修饰,拦截器的位置在source和channel之间;
Channel Selector:通道选择器,主要作用是根据用户配置将数据放到不同的Channel当中;
Channel:临时缓存数据;
Sink Runner:sink的运行器,主要是通过它来驱动Sink Processor,Sink Processor驱动Sink来从Channel当中获取数据;
Sink Processor:主要策略有负载均衡,故障转移以及直通;
Sink:从Channel当中取出数据放到不同的目的地。
1.2 Agent结构
Flume以agent为最小的独立运行单位。一个agent就是一个JVM。它是一个完整的数据收集工具,包括source、channel、sink三个核心组件。通过这些组件,Event 可以从一个地方流向另一个地方,如下图所示。
Source:负责接收event或通过特殊机制产生event,并将event批量放到一个或多个Channel。Source必须至少和一个channel关联,有驱动和轮询两种类型。
驱动型Source:是外部主动发送数据给Flume,驱动Flume接收数据。
轮询source:是Flume周期性主动去获取数据。
Channel:连接Source和Sink的组件,可以将它看做一个数据的缓冲区(数据队列),它可以将事件暂存到内存中也可以持久化到本地磁盘上,直到Sink处理完该事件。
Sink:Sink从Channel中取出事件,然后将数据发到别处。在日志数据较少时,可以将数据存储在文件系统中,并且设定一定的时间间隔保存数据。
1.3 flume可靠性
Flume在传输数据过程中,采用事物管理方式,保证数据传输过程中数据不会丢失,增强了数据传输的可靠性。缓存在channel中的数据如果采用了file channel,进程或者节点重启数据不会丢失。Flume在传输数据过程中,如果下一条的Flume节点故障或者数据接收异常时,可以自动切换到另外一路上继续传输。
二.Flume使用场景及概述
2.1 串行模式
将多个实例串行连接,实现数据传输。Flume实例过多,会影响传输效率。
2.2 聚合模式
每台web服务器部署一个flume实例采集日志,传输到一个集中的flume实例,再由此flume实例上传到hdfs,hbase,es,mysql等数据库,进行日志分析。
上图来自于官方截图,Agent4中的Sink不应该是Avro Sink,而应该是HDFS Sink。
2.3 复制模式
单source,多channel,sink模式,将事件event流向一个或多个目的地。这种模式下每个channel中的数据是相同的,sink可以选择将数据传输到不同的目的地。
2.4 负载均衡模式
单source,channel多sink;将多个sink逻辑上分到一个sink组,flume将数据发送到不同的sink,主要解决负载均衡和故障转移问题。
上图Agent2,Agent3,Agent4的Sink都应该是HDFS Sink,而不是Avro Sink。
三.Flume核心组件及实现
Flume核心组件主要是由Source,Channel,Sink三部分组成,这几个组件缺一不可。限于篇幅,本文将不会讨论源码内容。
3.1 Source组件
Source是数据源的总称,我们往往设定好源后,数据将源源不断的被抓取或者被推送。Source提供了两种机制:PollableSource(轮询拉取)和EventDrivenSource(事件驱动):
通过类图我们可以看到NetcatSource,ExecSource和HttpSource属于事件驱动模型。KafkaSource,SequenceGeneratorSource和JmsSource属于轮询拉取模型。Source接口继承了LifecycleAware接口,它的的所有逻辑的实现在接口的start和stop方法中进行。
Source接口定义的是最终的实现过程,比如通过日志抓取日志,这个抓取的过程和实际操作就是在对应的Source实现中,比如:ExecSource。那么这些Source实现由谁来驱动的呢?现在我们将介绍SourceRunner类。将看一下类继承结构图:
3.2 Channel组件
Channel用于连接Source和Sink,Source将日志信息发送到Channel,Sink从Channel消费日志信息;Channel是中转日志信息的一个临时存储,保存有Source组件传递过来的日志信息。
Channel接口定义了put,take,transaction三个方法,put方法是用来发送消息,take方法是获取消息,transaction是用于事务操作。
Channl中比较重要的是通道选择器,ChannelSelector的类结构图如下所示:
注:RelicatingChannelSelector和MultiplexingChannelSelector是两个通道选择器,第一个是复用型通道选择器,也就是默认的方式,会把接收到的消息发送给其他每个channel。第二个是多路通道选择器,这个会根据消息header中的参数进行通道选择。
3.3 Sink组件
Sink负责取出Channel中的消息数据,存储到文件系统,数据库,或者提交到远程服务器。
Sink是通过SinkFactory工厂来创建,提供了DefaultSinkFactory默认工厂,程序会查找org.apache.flume.conf.sink.
SinkType这个枚举类找到相应的Sink处理类,比如:org.apache.flume.sink.LoggerSink,如果没找到对应的处理类,直接通过Class.forName(className)进行直接查找实例化实现类。
Sink的类结构图如下:
与ChannelProcessor处理类对应的是SinkProcessor,由SinkProcessorFactory工厂类负责创建,SinkProcessor的类结构图如下:
FailoverSinkProcessor是故障转移处理器,当sink从通道拿数据信息时出错进行的相关处理,LoadBalancingSinkProcessor是负载Sink处理器;
我们重点看一下SinkSelector这个选择器结构类图:
RoundRobinSinkSelector是轮询选择器,RandomOrderSinkSelector是随机分配选择器。
通过本文的接触
大家对Apache Flume了解多少呢?
欢迎留言讨论