最近刚开始接触并使用flume,之前只是知道flume是用于日志收集的系统,没怎么系统研究过,最近工作中要用到flume,感觉还是flume的功能还是非常强大的,官网上有个非常详细的介绍,我觉得还是看看官网的介绍就足够了,比在网上搜到的东西讲的都好,要养成看官网文档的习惯: http://flume.apache.org/FlumeUserGuide.html



flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。 支持在日志系统中定制各类 数据 发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(比如文本、HDFS、Hbase等)的能力, flume的数据流由事件(Event)贯穿始终。事件是Flume的基本数据单位,它携带日志数据(字节数组形式)并且携带有头信息,这些Event由Agent外部的Source生成,当Source捕获事件后会进行特定的格式化,然后Source会把事件推入(单个或多个)Channel中。你可以把Channel看作是一个缓冲区,它将保存事件直到Sink处理完该事件。Sink负责持久化日志或者把事件推向另一个Source。




flume的一些核心概念:

  • Agent        使用JVM 运行Flume。每台机器运行一个agent,但是可以在一个agent中包含多个sources和sinks。
  • Client        生产数据,运行在一个独立的线程。
  • Source        从Client收集数据,传递给Channel。
  • 数据,运行在一个独立线程。
  • Channel        连接 sources 和 sinks ,这个有点像一个队列。
  • Events        可以是日志记录、 avro 对象等。



Flume以agent为最小的独立运行单位。一个agent就是一个JVM。单agent由Source、Sink和Channel三大组件构成,如下图:




Flume收集日志时是怎么处理Java堆栈信息 flume日志采集实训总结_ci


 




  值得注意的是,Flume提供了大量内置的Source、Channel和Sink类型。不同类型的Source,Channel和Sink可以自由组合。组合方式基于用户设置的配置文件,非常灵活。比如:Channel可以把事件暂存在内存里,也可以持久化到本地硬盘上。Sink可以把日志写入HDFS, HBase,甚至是另外一个Source等等。Flume支持用户建立多级流,也就是说,多个agent可以协同工作,并且支持Fan-in、Fan-out、Contextual Routing、Backup Routes,这也正是NB之处。如下图所示:



Flume收集日志时是怎么处理Java堆栈信息 flume日志采集实训总结_ci_02






从上面两个图可以看出来,flume其实非常强大,他可以支持从一个目录或流中收集数据,进行处理之后输出到hdfs或本地文件系统,也可以作为另外一个flume的数据源(source),


我这边有个需求就是收集不同节点上收集的数据,将其汇总后,不同格式的数据取不同的字段,然后写到ftp不同的目录中,因为前期不同节点上也是部署这单独的flume agent用于收集和处理数据入hdfs的,sink直接指向了hdfs,那么我这里需要做的就是在那两台flume 的agent上多加一个channel和sink,传到ftp上传的那个flume上


a1节点flume agent配置如下:
agent-a.channels = ch-1 ch-2
 agent-a.sources = src-1
 agent-a.sinks = avro-sink ftp-sink

 agent-a.channels.ch-1.type = memory
 agent-a.channels.ch-1.capacity = 10000
 agent-a.channels.ch-1.transactionCapacity  = 1000
 agent-a.channels.ch-1.byteCapacityBufferPercentage = 20
 agent-a.channels.ch-1.byteCapacity = 800000
 agent-a.channels.ch-1.checkpointDir = /home/hadoop/apache-flume-1.5.0.1-bin/data/a/checkpointDir
 agent-a.channels.ch-1.dataDirs = /home/hadoop/apache-flume-1.5.0.1-bin/data/a/dataDirs

 agent-a.channels.ch-2.type = memory
 agent-a.channels.ch-2.capacity = 10000
 agent-a.channels.ch-2.transactionCapacity  = 1000
 agent-a.channels.ch-2.byteCapacityBufferPercentage = 20
 agent-a.channels.ch-2.byteCapacity = 800000
 agent-a.channels.ch-2.checkpointDir = /home/hadoop/apache-flume-1.5.0.1-bin/data/a/ftpcheckpointDir
 agent-a.channels.ch-2.dataDirs = /home/hadoop/apache-flume-1.5.0.1-bin/data/a/ftpdataDirs

 agent-a.sinks.avro-sink.type = avro
 agent-a.sinks.avro-sink.hostname = hostname_a
 agent-a.sinks.avro-sink.port = 1422
 agent-a.sinks.avro-sink.channel = ch-1

 agent-a.sinks.ftp-sink.type = avro
 agent-a.sinks.ftp-sink.hostname = hostname_ftp
 agent-a.sinks.ftp-sink.port = 1422
 agent-a.sinks.ftp-sink.channel = ch-2

 agent-a.sources.src-1.type = spooldir
 agent-a.sources.src-1.channels = ch-1 ch-2
 agent-a.sources.src-1.spoolDir = /data/html/030.100.000.001/
 agent-a.sources.src-1.fileHeader = true
 agent-a.sources.src-1.fileHeaderKey = filename
 agent-a.sources.src-1.deletePolicy = immediate
a2节点的配置如下:
agent-b.channels = ch-2 ch-1 ch-3
 agent-b.sources = src-1
 agent-b.sinks = tab-sink avro-sink ftp-sink

 agent-b.channels.ch-1.type = file
 agent-b.channels.ch-1.capacity = 10000
 agent-b.channels.ch-1.transactionCapacity  = 5000
 agent-b.channels.ch-1.byteCapacityBufferPercentage = 20
 agent-b.channels.ch-1.byteCapacity = 80000
 agent-b.channels.ch-1.checkpointDir = /home/hadoop/apache-flume-1.5.0.1-bin/channel/checkpointDir_hdfs
 agent-b.channels.ch-1.dataDirs = /home/hadoop/apache-flume-1.5.0.1-bin/channel/dataDirs_hdfs


 agent-b.channels.ch-2.type = file
 agent-b.channels.ch-2.capacity = 10000 
 agent-b.channels.ch-2.transactionCapacity  = 5000  
 agent-b.channels.ch-2.byteCapacityBufferPercentage = 20
 agent-b.channels.ch-2.byteCapacity = 80000 
 agent-b.channels.ch-2.checkpointDir = /home/hadoop/apache-flume-1.5.0.1-bin/checkpointDir_hbase
 agent-b.channels.ch-2.dataDirs = /home/hadoop/apache-flume-1.5.0.1-bin/channel/dataDirs_hbase

 agent-b.channels.ch-3.type = file
 agent-b.channels.ch-3.capacity = 10000 
 agent-b.channels.ch-3.transactionCapacity  = 5000  
 agent-b.channels.ch-3.byteCapacityBufferPercentage = 20
 agent-b.channels.ch-3.byteCapacity = 80000 
 agent-b.channels.ch-3.checkpointDir = /home/hadoop/apache-flume-1.5.0.1-bin/checkpointDir_ftp
 agent-b.channels.ch-3.dataDirs = /home/hadoop/apache-flume-1.5.0.1-bin/channel/dataDirs_ftp

 agent-b.sinks.avro-sink.type = avro
 agent-b.sinks.avro-sink.hostname = 192.168.10.14
 agent-b.sinks.avro-sink.port = 1422
 agent-b.sinks.avro-sink.channel = ch-1

 agent-b.sinks.tab-sink.debug = true
 agent-b.sinks.tab-sink.batchSize = 1000
 agent-b.sinks.tab-sink.channel = ch-2
 ****

 agent-b.sinks.ftp-sink.type = avro
 agent-b.sinks.ftp-sink.hostname = hostname_ftp
 agent-b.sinks.ftp-sink.port = 1422
 agent-b.sinks.ftp-sink.channel = ch-3

 agent-b.sources.src-1.type = spooldir
 agent-b.sources.src-1.channels = ch-2 ch-1 ch-3
 agent-b.sources.src-1.deserializer = LINE
 #agent-b.sources.src-1.spoolDir = /data/empty/
 agent-b.sources.src-1.spoolDir = /data/b/bcp/
 agent-b.sources.src-1.fileHeader = true
 agent-b.sources.src-1.fileHeaderKey = filename
 agent-b.sources.src-1.deletePolicy = never在上传ftp的flume节点的配置如下:
uploadtoftp.channels = ch-3
 uploadtoftp.sources = src-1
 uploadtoftp.sinks = ftp-sink

 uploadtoftp.channels.ch-3.type = file
 uploadtoftp.channels.ch-3.capacity = 10000
 uploadtoftp.channels.ch-3.transactionCapacity  = 5000
 uploadtoftp.channels.ch-3.byteCapacityBufferPercentage = 20
 uploadtoftp.channels.ch-3.byteCapacity = 80000
 uploadtoftp.channels.ch-3.checkpointDir = /home/hadoop/lx/data/channel/checkpointDir_hdfs
 uploadtoftp.channels.ch-3.dataDirs = /home/hadoop/lx/data/channel/dataDirs_hdfs

 uploadtoftp.sources.src-1.type = avro
 uploadtoftp.sources.src-1.bind = 0.0.0.0
 uploadtoftp.sources.src-1.port = 1423
 uploadtoftp.sources.src-1.channels = ch-3

 uploadtoftp.sinks.ftp-sink.type = file_roll
 uploadtoftp.sinks.ftp-sink.sink.directory = /home/hadoop/lx/data-output
 uploadtoftp.sinks.ftp-sink.channel = ch-3

 uploadtoftp.sinks.ftp-sink.type = com.lx.filesink.MultiFileSink
 uploadtoftp.sinks.ftp-sink.file.path = /home/hadoop/lx/data-output/flume/lx_mysink/%y-%m-%d
 uploadtoftp.sinks.ftp-sink.file.filePrefix = lxtestlog-%{y}%{m}-%{d}-
 uploadtoftp.sinks.ftp-sink.file.srctype = air1,air2
 uploadtoftp.sinks.ftp-sink.extractIndexs.air1 = 3,6,7,9,13,14
 uploadtoftp.sinks.ftp-sink.extractIndexs.air2 = 4,5,6,7
 uploadtoftp.sinks.ftp-sink.typeIndexs.air1 = 0
 uploadtoftp.sinks.ftp-sink.typeIndexs.air2 = 0
 uploadtoftp.sinks.ftp-sink.ftp.url = ftp-url
 uploadtoftp.sinks.ftp-sink.ftp.port = ftp-port
 uploadtoftp.sinks.ftp-sink.ftp.user = ftp-user
 uploadtoftp.sinks.ftp-sink.ftp.passwd = ftp-passwd
 uploadtoftp.sinks.ftp-sink.file.ftppath = /lxtest/data/
 uploadtoftp.sinks.ftp-sink.file.localtmppath = /home/hadoop/lx/data-output/ftpsink-out/
 uploadtoftp.sinks.ftp-sink.file.useLocalTimeStamp = true
 uploadtoftp.sinks.ftp-sink.file.txnEventMax = 10000
 uploadtoftp.sinks.ftp-sink.file.maxOpenFiles = 5


其中MultiFileSink为自定义的一个ftp多目录输出的yigeflume sink,当然涉及到ftp-sink.*的这些配置都是在自定义方法中的输入参数context中设置的,不同的数据做不同处理的逻辑也是在MultiFileSink中处理的。


之前一直想不明白ftp节点是如何接收数据的,自己做了个简单的实验,配置source.type=arvo hostname port之后,在本地监听1422端口,就发现启动agent之后,也会启动一个1422的端口的实例,应该是用于接收数据了,当然要验证的话也很简单,将以上的三个配好测一下就ok。