介绍
概述
Apache Flume是一个分布式的,可靠的,高可用的系统,用于高效地从多个不同的数据源收集,汇总及迁移大量日志数据到集中的数据储存。
Apache Flume并仅限于日志数据聚集使用。由于的数据源可定制的,Flume可用于传递大量事件数据包括但不限于网络流量数据,社交媒体生成的数据,email信息以及几乎它让任意其它可能的数据源。
Apache Flume是Apache软件基金会的顶级项目。
目前有两条代码线路可用,0.9.x和1.x。
0.9.x的文档参见[Flume 0.9.x User Guide。
本文档适用于1.4.x。
新用户建议使用1.x版本,在最近的框架中改进了性能和配置灵活性。
系统要求
- Java运行时环境—Java1.7及以后版本
- 内存—sources, channels或sinks配置使用的足够内存
- 磁盘空间—channels或sinks配置使用的磁盘空间
- 目录权限—agent使用的目录要有读写权限
架构
数据流模型
Flume事件定义为一个数据流单元,具有字节负载和一个可选的字符串集合属性。Flume agent就是一个JVM进程,通过agent事件流可以从一个外部源流向下一个目的地。
Flume source可以从外部源消费事件,如web server。外部源用可被source识别的格式将事件发送到source。例如,Avro Flume source可以用于从Avro客户端或者流中的其它Flume agents(从Avro sink发送事件)接收Avro事件。可使用Thrift Flume source定义类似的流,用于从Thrift Sink,Thrift RPC 客户端或Thrift客户端(用从Flume thrift协议生成的任意语言编写)接收事件。当Flume source接收一个事件是,会将事件存储到一个或多个channel。channel是被动存储的,会一直保存事件直到被Flume sink消费。文件channel是一个例子—由本地文件系统支持。sink从channel移除事件并将事件放到外部库中,如HDFS(通过Flume HDFS sink)或者转发给流中的下一个Flume agent的Flume source。agent中的source和sink异步运行,事件存储在中间的channel中。
复杂流
Flume允许用户构建多跳流,在到达最终目的地前,事件在多个agent中传递。也支持fan-in和fan-out流,上下文路由和为失败跳准备的备用路由。
可靠性
事件存储在每个agent的channel中。之后事件会被传递到流中的下个agent或者最终的存储库(如HDFS)。事件只有在存储到下个agent的channel或者最终的存储库中以后才会在原来的channel中溢出。这就是Flume中单跳信息传递语义提供的端到端可靠性。
Flume采用事务来保证事件传递的可靠性。source和sink分别封装在storage/retrieval事务中。这保证了事件集合能可靠地从流中的一点传递到另一点。对于多跳流的情况,前一个跳的sink和后一个跳的source都有自己的事务运行保证数据能够在下一个channel安全地存储。
可恢复性
事件存储在channel中,可以从错误中恢复。Flume提供本地文件系统支持的持久文件channel。也有内存channel,将事件存储在内存队列中,存取速度更快,但是当agent进程down了还在内存中的事件就无法恢复了。
安装
安装agent
Flume agent配置存储在本地配置文件。配置文件是遵循Java properties文件格式的文本文件。可以在一个配置文件中配置一或多个agent。配置文件包含agent中每个source,sink和channel的属性,以及它们是如何连接在一起形成数据流。
配置单独的组件
流中的每个组件(source,sink或channel)都有名称,类型以及一组为类型和实例化指定的属性。例如,Avro source需要hostname(或IP地址)以及端口号,当作接收数据的源。内存channel可以设置最大队列大小("capacity"),HDFS sink需要知道文件系统的URI,用于创建文件的路径,文件rotation的频率("hdfs.rollInterval")等。组件的所有这类属性都需要在Flume agent的属性文件中进行设置。
把各部分连接起来
agent需要知道哪些单独的组件需要加载,以及它们如何连接形成整个流。通过在agent中罗列每个source,sink和channel的名称来指定,然后再指定每个sink和source连接的channel。例如,agent通过名为file-channel的文件channel将事件从名为avroWeb的Avro source传递到名为hdfs-cluster1的HDFS sink。配置文件会包含这些组件的名称,file-channel作为avroWeb source和hdfs-cluster1 sink的共享channel。
启动agent
使用shell脚本flume-ng启动agent,脚本在Flume的bin目录中。你需要指定agent的名称,配置目录以及配置文件:
$ bin/flume-ng agent -n $agent_name -c conf -f conf/flume-conf.properties.template
agent会启动运行给定properties文件中的source和sink。
一个简单的示例
这里,给出一个配置文件的示例,描述了单节点Flume部署。这个配置可以生成事件,随后记录到控制台。
# example.conf: A single-node Flume configuration
# 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。a1有一个监听44444端口的source,一个内存channel,以及将事件数据记录到控制台的sink。配置文件先命名了多个组件,然后描述了它们的类型和配置参数。配置文件可以定义多个agent;当一个给定Flume进程启动时,会传入一个标记说明启动哪个agent。
给定这个配置文件,我们可以按照如下方式启动Flume:
$ bin/flume-ng agent --conf conf --conf-file example.conf --name a1 -Dflume.root.logger=INFO,console
注意,在一个完整部署中,我们会包含一个选项:--conf=<conf-dir>
。<conf-dir>
目录会包含一个shell脚本flume-env.sh
和一个log4j properties file。在这个示例中,我们传递了一个Java选项来强制Flume记录事件到控制台,我们没有自定义环境脚本。
从另一个的终端,可以telnet 44444端口,向Flume发送一个事件:
$ telnet localhost 44444
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
Hello world! <ENTER>
OK
Flume终端会在log信息中输出事件:
12/06/19 15:32:19 INFO source.NetcatSource: Source starting
12/06/19 15:32:19 INFO source.NetcatSource: Created serverSocket:sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:44444]
12/06/19 15:32:34 INFO sink.LoggerSink: Event: { headers:{} body: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 0D Hello world!. }
恭喜—你已经成功配置并部署了一个Flume agent!之后会介绍agent配置更多细节。
记录原始数据
在很多生产环境中,记录流过管线的原始数据流并不是期望的行为,因为这可能导致泄露敏感数据或者安全相关的配置,如secret keys。默认地,Flume不会记录这些信息。如果数据管线损坏,Flume会尝试提供一些信息帮助调试问题。
用事件管线调试问题的一种方法是设置一个额外的内存channel,连接到可将所有事件数据输出到Flume日志的Logger Sink。某些情况下,这种方法还不足以满足需求。
为了启用事件相关和配置相关的数据记录,除了log4j属性之外,还必须设置一些Java系统属性。
为了启用配置相关记录,设置Java系统属性-Dorg.apache.flume.log.printconfig=true
。可通过命令行传递或者在flume-env.sh
脚本中的JAVA_OPTS
处设置。
为了启用数据记录,设置Java系统属性-Dorg.apache.flume.log.rawdata=true
,方法同上。对于大多数组件来说,log4j的记录等级必须也设置为DEBUG
或TRACE
,使事件特定记录出现在Flume日志中。
下面是一个启用配置记录和原始数据记录的示例,将输出到控制台的Log4j日志等级设置为DEBUG
:
$ bin/flume-ng agent --conf conf --conf-file example.conf --name a1 -Dflume.root.logger=DEBUG,console -Dorg.apache.flume.log.printconfig=true -Dorg.apache.flume.log.rawdata=true
基于Zookeeper的配置
Flume支持通过Zookeeper配置agent。这是一个实验阶段的特性。配置文件需要上传到Zookeeper,在可配置的前缀下。配置文件存储在Zookeeper节点数据中。下面是agent a1和a2的Zookeeper节点树:
- /flume
|- /a1 [Agent config file]
|- /a2 [Agent config file]
一旦配置文件上传,可使用下面的选项启动agent:
$ bin/flume-ng agent –conf conf -z zkhost:2181,zkhost1:2181 -p /flume –name a1 -Dflume.root.logger=INFO,console
参数 | 默认值 | 描述 |
---|---|---|
z | - | Zookeeper连接字符串。hostname:port形式并以逗号分隔的列表 |
p | /flume | 在Zookeeper中存储agent配置的根路径 |
安装第三方插件
Flume有一个完全基于插件的架构。Flume有很多sources,channels,sinks和serializers等,很多实现都独立于Flume。
可以包含自定义的Flume组件,在fulme-env.sh脚本的FLUME_CLASSPATH变量中添加jar包,Flume现在支持一个特殊的路径plugins.d
,会自动识别以特定格式打包的插件。这种方式让管理插件打包问题以及调试和解决类的问题更加容易,尤其是库依赖冲突问题。
plugins.d目录
plugins.d
目录位于$FLUME_HOME/plugins.d
。在启动时,启动脚本flume-ng
会查看plugins.d
目录找出符合以下格式的插件,然后在启动java
时包含它们。
插件的目录结构
plugins.d
目录中的每个插件(子目录)最多可以包含三个子目录:
- lib—插件的jar包
- libext—插件依赖的jar包
- native—任何依赖放入本地库,如
.so
文件
下面是两个插件示例:
plugins.d/
plugins.d/custom-source-1/
plugins.d/custom-source-1/lib/my-source.jar
plugins.d/custom-source-1/libext/spring-core-2.5.6.jar
plugins.d/custom-source-2/
plugins.d/custom-source-2/lib/custom.jar
plugins.d/custom-source-2/native/gettext.so
数据提取
Flume支持多种从外部源提取数据的机制。
RPC
Flume中的Avro客户端可使用avro RPC机制发送指定文件给Flume Avro source:
$ bin/flume-ng avro-client -H localhost -p 41414 -F /usr/logs/log.10
上面的命令会发送/usr/logs/log.10的内容到监听41414端口的Flume source。
执行命令
有一个exec source可以执行给定命令并且消费其输出。单行输出,文本后跟着'\r'
,'\n'
或者两个都有。
注意:Flume不支持tail作为source。可以将tail命令封装到exec source中。
网络流
Flume支持下面的机制,从流行的日志流类型中读取数据,如:
- Avro
- Thrift
- Syslog
- Netcat
设置multi-agent流
为了在多个agent之间传递数据,前一个agent的sink和当前agent的source都是avro类型,sink指向了source的IP地址和端口。
合并
在日志收集中非常常见的现象是多个日志源发送数据到少数几个连接到存储系统的消费者agent。例如,上百个web服务器发送日志到十几个agent,然后写入到HDFS集群。
配置多个一级代理包含avro sink,所有sink都指向单一agent的一个avro source(同样情况,也可以使用thrift sources/sinks/channels)。二级agent的source会合并接收的事件发送到单个channel,然后sink会将事件消费到最终的目的地。
复用流
Flume支持复用事件流到一个或多个目的地。通过定义复用器来实现,复用器可以复制事件或者选择性地将事件路由到一个或多个channel。
上面的示例展示了从agent "foo"一个source发送事件到三个不同的channel。事件可复制或者复用。在复制流的情况下,每个事件都会发送到所有三个channel中。对于复用的情况,当事件属性匹配了预先配置值时,事件会发送到可用channel的子集。例如,如果名为"txnType"事件属性设置为"customer",则事件应该传递到channel1和channel3,如果设置为"vendor"则应该传递到channel2,否则传递到channel3。具体的映射可在agent的配置文件中设置。