@Author : Spinach | GHB
@Link : http://blog.csdn.net/bocai8058
Flume 作为 cloudera 开发的实时日志收集系统,受到了业界的认可与广泛应用。Flume 初始的发行版本目前被统称为 Flume OG(original generation),属于 cloudera。后于2009年被捐赠了apache软件基金会,为hadoop相关组件之一。尤其近几年随着flume的不断被完善以及升级版本的逐一推出,特别是Flume NG(next generation);同时Flume内部的各种组件不断丰富,用户在开发的过程中使用的便利性得到很大的改善,现已成为apache top项目之一。
apache Flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(比如文本、HDFS、Hbase等)的能力。
在整个数据的传输的过程中,流动的是event,即事务保证是在event级别进行的。那么什么是event呢?
1. event将传输的数据进行封装,是flume传输数据的基本单位,如果是文本文件,通常是一行记录,event也是事务的基本单位。
2. event从source,流向channel,再到sink,本身为一个字节数组,并可携带headers(头信息)信息。
3. event代表着一个数据的最小完整单元,从外部数据源来,向外部的目的地去。
Flume的核心是agent,把数据从数据源(source)收集过来,在将收集到的数据送到指定的目的地(sink)。为了保证输送的过程一定成功,在送到目的地(sink)之前,会先缓存数据(channel),待数据真正到达目的地(sink)后,flume再删除自己缓存的数据。
Flume以agent为最小的独立运行单位。一个agent就是一个JVM。它是一个完整的数据收集工具,含有三个核心组件,分别是source、 channel、 sink。
备注:不过flume的持久化也是有容量限制的,比如内存如果超过一定的量,不够分配,也一样会爆掉。
sources类型 | 描述 | channels类型 | 描述 | sinks类型 | 描述 |
---|---|---|---|---|---|
avro | 监听Avro端口并接收Avro Client的流数据 | memory | Event数据存储在内存中 | avor | 数据被转换成Avro Event,然后发送到配置的RPC端口上 |
thrift | 监听Thrift端口并接收Thrift Client的流数据 | jdbc | Event数据存储在持久化存储中,当前Flume Channel内置支持Derby | thrift | 数据被转换成Thrift Event,然后发送到配置的RPC端口上 |
exec | 基于Unix的command在标准输出上生产数据 | file | Event数据存储在磁盘文件中 | hive | 数据导入到HIVE中 |
jms | 从JMS(Java消息服务)采集数据 | SPILLABLEMEMORY | Event数据存储在内存中和磁盘上,当内存队列满了,会持久化到磁盘文件(当前试验性的,不建议生产环境使用) | logger | 数据写入日志文件 |
spooldir | 监听指定目录 | PseudoTxnMemoryChannel | 测试用途 | hdfs | 数据写入HDFS |
KafkaSource | 采集Kafka topic中的message | KafkaChannel | Event存储在kafka集群 | KafkaSink | 数据写到Kafka Topic |
netcat | 监听端口(要求所提供的数据是换行符分隔的文本) | Custom | 自定义Channel实现 | hbase | 数据写入HBase数据库 |
seq | 序列产生器,连续不断产生event,用于测试 | null | 丢弃到所有数据 | ||
syslogtcp、syslogudp、multiport_syslogtcp | 采集syslog日志消息,支持单端口TCP、多端口TCP和UDP日志采集 | DatasetSink | 写数据到Kite Dataset,试验性质的 | ||
http | 接收HTTP POST和GET数据 | Custom | 自定义Sink实现 | ||
其他 | 其他 |
sources类型 | 描述 |
---|---|
replicating | 默认管道选择器: 每一个管道传递的都是相同的events |
multiplexing | 多路复用通道选择器: 依据每一个event的头部header的地址选择管道 |
Custom | 自定义selector实现 |
# example.conf: A single-node Flume configuration
# Name the components on this agent
a1.sources = r1
a1.channels = c1
a1.sinks = k1
# Describe/configure the source
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /home/ghb/HadoopCluster/Call
a1.sources.r1.fileHeader = true
#a1.sources.r1.type = exec
#a1.sources.r1.command = tail -F /home/ghb/HadoopCluster/Call/CallLog.log
#a1.sources.r1.fileHeader = true
#a1.sources.r1.deserializer.outputCharset=UTF-8
# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# Describe the sink
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.topic = CallLog
a1.sinks.k1.kafka.bootstrap.servers =127.0.0.1:6667
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks=1
#a1.sinks.k1.type = hdfs
#a1.sinks.k1.hdfs.path = hdfs://hadoop0:9000/CallLog
#a1.sinks.k1.hdfs.filePrefix = log_%Y%m%d_%H
#a1.sinks.k1.hdfs.writeFormat= Text
#a1.sinks.k1.hdfs.fileType = CompressedStream
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
# Weblog.conf: A agent configuration
# list sources, sinks and channels in the agent
agent_foo.sources = avro-AppSrv-source
agent_foo.sinks = avro-forward-sink
agent_foo.channels = file-channel
# define the flow
agent_foo.sources.avro-AppSrv-source.channels = file-channel
agent_foo.sinks.avro-forward-sink.channel = file-channel
# avro sink properties
agent_foo.sources.avro-forward-sink.type = avro
agent_foo.sources.avro-forward-sink.hostname = 10.1.1.100
agent_foo.sources.avro-forward-sink.port = 10000
# configure other pieces
#...
# HDFS.conf: other agent configuration
# list sources, sinks and channels in the agent
agent_foo.sources = avro-collection-source
agent_foo.sinks = hdfs-sink
agent_foo.channels = mem-channel
# define the flow
agent_foo.sources.avro-collection-source.channels = mem-channel
agent_foo.sinks.hdfs-sink.channel = mem-channel
# avro sink properties
agent_foo.sources.avro-collection-source.type = avro
agent_foo.sources.avro-collection-source.bind = 10.1.1.100
agent_foo.sources.avro-collection-source.port = 10000
# configure other pieces
#...
# fan_out_flow.conf: an agent configuration
# list the sources, sinks and channels in the agent
agent_foo.sources = avro-AppSrv-source1
agent_foo.sinks = hdfs-Cluster1-sink1 avro-forward-sink2
agent_foo.channels = mem-channel-1 file-channel-2
# set channels for source
agent_foo.sources.avro-AppSrv-source1.channels = mem-channel-1 file-channel-2
# set channel for sinks
agent_foo.sinks.hdfs-Cluster1-sink1.channel = mem-channel-1
agent_foo.sinks.avro-forward-sink2.channel = file-channel-2
# channel selector configuration
agent_foo.sources.avro-AppSrv-source1.selector.type = multiplexing
agent_foo.sources.avro-AppSrv-source1.selector.header = State
agent_foo.sources.avro-AppSrv-source1.selector.mapping.CA = mem-channel-1
agent_foo.sources.avro-AppSrv-source1.selector.mapping.AZ = file-channel-2
agent_foo.sources.avro-AppSrv-source1.selector.mapping.NY = mem-channel-1 file-channel-2
agent_foo.sources.avro-AppSrv-source1.selector.default = mem-channel-1
# configure other pieces
#...
# example1.conf: This is a generic configuration for the configuration file
# list the sources, sinks and channels for the agent
<Agent>.sources = <Source>
<Agent>.sinks = <Sink>
<Agent>.channels = <Channel1> <Channel2>
# properties for sources
<Agent>.sources.<Source>.<someProperty> = <someValue>
# properties for sinks
<Agent>.sources.<Sink>.<someProperty> = <someValue>
# channel selector configuration
# ...
# Bind the source and sink to the channel
<Agent>.sources.<Source>.channels = <Channel1> <Channel2> ...
<Agent>.sinks.<Sink>.channel = <Channel1>
$ bin/flume-ng agent -n $agent_name -c conf -f conf/flume-conf.conf -Dflume.root.logger=INFO,console
# $flume-ng --help
Usage: /home/ghb/HadoopCluster/flume-1.7.0/bin/flume-ng [options]...
commands:
help display this help text
agent run a Flume agent
avro-client run an avro Flume client
version show Flume version info
global options:
--conf,-c use configs in directory
--classpath,-C append to the classpath
--dryrun,-d do not actually start Flume, just print the command
--plugins-path colon-separated list of plugins.d directories. See the
plugins.d section in the user guide for more details.
Default: $FLUME_HOME/plugins.d
-Dproperty=value sets a Java system property value
-Xproperty=value sets a Java -X option
agent options:
--name,-n the name of this agent (required)
--conf-file,-f specify a config file (required if -z missing)
--zkConnString,-z specify the ZooKeeper connection to use (required if -f missing)
--zkBasePath,-p specify the base path in ZooKeeper for agent configs
--no-reload-conf do not reload config file if changed
--help,-h display help text
avro-client options:
--rpcProps,-P RPC client properties file with server connection params
--host,-H hostname to which events will be sent
--port,-p port of the avro source
--dirname directory to stream to avro source
--filename,-F text file to stream to avro source (default: std input)
--headerFile,-R File containing event headers as key/value pairs on each new line
--help,-h display help text
Either --rpcProps or both --host and --port must be specified.
Note that if directory is specified, then it is always included first
in the classpath.
Flume主要由3个重要的组件构成:
1. Source: 完成对日志数据的收集,分成transtion 和 event 打入到channel之中。
2. Channel: Flume Channel主要提供一个队列的功能,对source提供中的数据进行简单的缓存。
3. Sink: Flume Sink取出Channel中的数据,进行相应的存储文件系统,数据库,或者提交到远程服务器。
1) log4j有一个TimeRolling的插件,可以把log4j分割的文件到spool目录。
2) 基本实现了实时的监控。
3) Flume在传完文件之后,将会修改文件的后缀,变为.COMPLETED(后缀也可以在配置文件中灵活指定)
1) ExecSource可以实现对日志的实时收集,但是存在Flume不运行或者指令执行出错时,将无法收集到日志数据,无法何证日志数据的完整性。
2) SpoolSource虽然无法实现实时的收集数据,但是可以使用以分钟的方式分割文件,趋近于实时。
3) 总结:如果应用无法实现以分钟切割日志文件的话,可以两种收集方式结合使用。
Flume Sink在设置存储数据时,可以向文件系统中,数据库中,hadoop中储数据,在日志数据较少时,可以将数据存储在文件系中,并且设定一定的时间间隔保存数据。在日志数据较多时,可以将相应的日志数据存储到Hadoop中,便于日后进行相应的数据分析。
如果你想把可文本化的日志数据提取到HDFS,那么Flume是非常适合的。
对于其他场景,有些东西是需要考量的:Flume被设计用来传输、提取定期生成的数据的,这些数据是传输在相对稳定的、可能是复杂的拓扑结构上的。每个数据就是一个event。“event data”的概念是非常广泛的。对于Flume而言,一个event就是一个blob字节数据。这个event的大小是有限制的,例如,不能大于内存或硬盘或单机可以存储的大小。事实上,flume的event可以是任何东西,从日志文本到图片文件。Event的关键点是不断生成、流式的。如果你的数据不是的定期生成的(比如一次性的向Hadoop集群导入数据),Flume可以工作,但是有点杀鸡用牛刀了。Flume喜欢相对稳定的拓扑结构。你的拓扑结构不必是不可改变的,因为Flume可以在不丢失数据的前提下处理拓扑结构的改变,并且能容忍由于故障转移导致的周期性的重新配置。但如果你每天都要改变拓扑结构,那么Flume将不能很好的工作,因为重新配置会产生开销。
简而言之,有两点:
1. 数据。数据是定期生成的。
2. 网络拓扑相对稳定。
Flume的数据流由事件(Event)贯穿始终。事件是Flume的基本数据单位,它携带日志数据(字节数组形式)并且携带有头信息,这些Event由Agent外部的Source生成,当Source捕获事件后会进行特定的格式化,然后Source会把事件推入(单个或多个)Channel中。你可以把Channel看作是一个缓冲区,它将保存事件直到Sink处理完该事件。Sink负责持久化日志或者把事件推向另一个Source。