Flume采集处理日志文件
-
Flume简介
Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。
-
系统功能
-
日志收集
-
Flume最早是Cloudera提供的日志收集系统,目前是Apache下的一个孵化项目,Flume支持在日志系统中定制各类数据发送方,用于收集数据。
-
数据处理
Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力 Flume提供了从console(控制台)、RPC(Thrift-RPC)、text(文件)、tail(UNIX tail)、syslog(syslog日志系统,支持TCP和UDP等2种模式),exec(命令执行)等数据源上收集数据的能力。
-
工作方式
Flume采用了多Master的方式。为了保证配置数据的一致性,Flume[1] 引入了ZooKeeper,用于保存配置数据,ZooKeeper本身可保证配置数据的一致性和高可用,另外,在配置数据发生变化时,ZooKeeper可以通知Flume Master节点。Flume Master间使用gossip协议同步数据。
-
流程结构
Flume的结构主要分为三部分:source、channel以及sink.其中source为源头,负责采集日志;channel为通道,负责传输和暂时储存;sink为目的地,将采集到的日志保存起来。在真正日志采集的过程中,根据待采集日志的类型以及存储需求,选择相应的类型的source、channel和sink进行配置,从而将日志采集并且保存起来。
-
Flume采集日志方案
-
需求分析
-
日志分类
-
-
操作系统:linux
日志更新类型:产生新日志,原日志结尾处追加
-
采集时间需求
采集周期:短周期(一天之内)
-
采集方案
-
采集构架
-
使用flume采集日志文件的过程较简洁,只需选择恰当的source、channel和sink并且配置起来即可,若有特殊需求也可自己进行二次开发实现个人需求。
具体过程为:按照需求配置一个agent,选取适当的source和sink,然后启动该agent,开始采集日志。
-
source
flume提供多种source供用户进行选择,尽可能多的满足大部分日志采集的需求,常用的source的类型包括avro、exec、netcat、spooling-directory和syslog等。具体的使用范围和配置方法详见source.
-
channel
flume中的channel不如source和sink那么重要,但却是不可忽视的组成部分。常用的channel为memory-channel,同时也有其他类型的channel,如JDBC、file-channel、custom-channel等,详情见channel.
-
sink
flume的sink也有很多种,常用的包括avro、logger、HDFS、hbase以及file-roll等,除此之外还有其他类型的sink,如thrift、IRC、custom等。具体的使用范围和使用方法详见sink.
-
Flume处理日志
Flume不止可以采集日志,还可以对日志进行简单的处理,在source处可以通过interceptor对日志正文处的重要内容进行过滤提取,在channel处可以通过header进行分类,将不同类型的日志投入不同的通道中,在sink处可以通过正则序列化来将正文内容进行进一步的过滤和分类。
-
Flume Source Interceptors
Flume可以通过interceptor将重要信息提取出来并且加入到header中,常用的interceptor有时间戳、主机名和UUID等,用户也可以根据个人需求编写正则过滤器,将某些特定格式的日志内容过滤出来,以满足特殊需求。
-
Flume Channel Selectors
Flume可以根据需求将不同的日志传输进不同的channel,具体方式有两种:复制和多路传输。复制就是不对日志进行分组,而是将所有日志都传输到每个通道中,对所有通道不做区别对待;多路传输就是根据指定的header将日志进行分类,根据分类规则将不同的日志投入到不同的channel中,从而将日志进行人为的初步分类。
-
Flume Sink Processors
Flume在sink处也可以对日志进行处理,常见的sink处理器包括custom、failover、load balancing和default等,和interceptor一样,用户也可以根据特殊需求使用正则过滤处理器,将日志内容过滤出来,但和interceptor不同的是在sink处使用正则序列化过滤出的内容不会加入到header中,从而不会使日志的header显得过于臃肿。
-
附录
-
常见的source
-
avro source
-
-
avro可以监听和收集指定端口的日志,使用avro的source需要说明被监听的主机ip和端口号,下面给出一个具体的例子:
a1.sources = r1
a1.channels = c1
a1.sources.r1.type = avro
a1.sources.r1.channels = c1
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = 4141
-
exec source
exec可以通过指定的操作对日志进行读取,使用exec时需要指定shell命令,对日志进行读取,下面给出一个具体的例子:
a1.sources = r1
a1.channels = c1
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /var/log/secure
a1.sources.r1.channels = c1
-
spooling-directory source
spo_dir可以读取文件夹里的日志,使用时指定一个文件夹,可以读取该文件夹中的所有文件,需要注意的是该文件夹中的文件在读取过程中不能修改,同时文件名也不能修改。下面给出一个具体的例子:
agent-1.channels = ch-1
agent-1.sources = src-1
agent-1.sources.src-1.type = spooldir
agent-1.sources.src-1.channels = ch-1
agent-1.sources.src-1.spoolDir = /var/log/apache/flumeSpool
agent-1.sources.src-1.fileHeader = true
-
syslog source
syslog可以通过syslog协议读取系统日志,分为tcp和udp两种,使用时需指定ip和端口,下面给出一个udp的例子:
a1.sources = r1
a1.channels = c1
a1.sources.r1.type = syslogudp
a1.sources.r1.port = 5140
a1.sources.r1.host = localhost
a1.sources.r1.channels = c1
-
常见的channel
Flume的channel种类并不多,最常用的是memory channel,下面给出例子:
a1.channels = c1
a1.channels.c1.type = memory
a1.channels.c1.capacity = 10000
a1.channels.c1.transactionCapacity = 10000
a1.channels.c1.byteCapacityBufferPercentage = 20
a1.channels.c1.byteCapacity = 800000
-
常见的sink
-
logger sink
-
logger顾名思义,就是将收集到的日志写到flume的log中,是个十分简单但非常实用的sink
-
avro sink
avro可以将接受到的日志发送到指定端口,供级联agent的下一跳收集和接受日志,使用时需要指定目的ip和端口:例子如下:
a1.channels = c1
a1.sinks = k1
a1.sinks.k1.type = avro
a1.sinks.k1.channel = c1
a1.sinks.k1.hostname = 10.10.10.10
a1.sinks.k1.port = 4545
-
file roll sink
file_roll可以将一定时间内收集到的日志写到一个指定的文件中,具体过程为用户指定一个文件夹和一个周期,然后启动agent,这时该文件夹会产生一个文件将该周期内收集到的日志全部写进该文件内,直到下一个周期再次产生一个新文件继续写入,以此类推,周而复始。下面给出一个具体的例子:
a1.channels = c1
a1.sinks = k1
a1.sinks.k1.type = file_roll
a1.sinks.k1.channel = c1
a1.sinks.k1.sink.directory = /var/log/flume
-
hdfs sink
hdfs与file roll有些类似,都是将收集到的日志写入到新创建的文件中保存起来,但区别是file roll的文件存储路径为系统的本地路径,而hdfs的存储路径为分布式的文件系统hdfs的路径,同时hdfs创建新文件的周期可以是时间,也可以是文件的大小,还可以是采集日志的条数。具体实例如下:
a1.channels = c1
a1.sinks = k1
a1.sinks.k1.type = hdfs
a1.sinks.k1.channel = c1
a1.sinks.k1.hdfs.path = /flume/events/%y-%m-%d/%H%M/%S
a1.sinks.k1.hdfs.filePrefix = events-
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.roundValue = 10
a1.sinks.k1.hdfs.roundUnit = minute
-
hbase sink
hbase是一种数据库,可以储存日志,使用时需要指定存储日志的表名和列族名,然后agent就可以将收集到的日志逐条插入到数据库中。例子如下:
a1.channels = c1
a1.sinks = k1
a1.sinks.k1.type = hbase
a1.sinks.k1.table = foo_table
a1.sinks.k1.columnFamily = bar_cf
a1.sinks.k1.serializer = org.apache.flume.sink.hbase.RegexHbaseEventSerializer
a1.sinks.k1.channel = c1
概述
系统环境
- 操作系统:win7 64
- JDK:1.6.0_43
资源下载
- Maven:3.3.3
下载、安装、入门参考:1. Maven - 开始和2. 创建一个简单的Maven项目 - Flume:1.6.0
下载apache-flume-1.6.0-bin.tar.gz,并解压到合适的目录(e.g. F:\temp\apache-flume-1.6.0-bin) - MongoDB:3.2.3
下载mongodb-win32-x86_64-3.2.3-signed.msi,并安装到合适的目录(e.g. D:\develop\MongoDB)
辅助资源下载
- MongoDB Java Driver:2.13.0
下载地址:mongo-java-driver-2.13.0.jar
下载之后放入Flume安装目录的lib下。 - flume-ng-mongodb-sink
Flume需要这个,才能把数据写到MongoDB中
下载地址:flume-ng-mongodb-sink
这是一个基于Maven的源代码,package之后,将jar包放到Flume安装目录的lib下。
初始化
数据初始化
- 新建一个目录,作为dbpath
e.g. D:\develop\MongoDB\mydata - 启动监听服务 - CMD运行
D:\develop\MongoDB\bin\mongod --dbpath=D:\develop\MongoDB\mydata
配置Flume
- 生成flume-env.ps1
在安装目录的conf/下,复制flume-env.ps1.template,重命名为flume-env.ps1 - 修改log4j.properties
在安装目录的conf/下,修改文件log4j.properties;修改flume.root.logger=INFO,console
实现
Flume到MongoDB
agent.sources = so1 agent.channels = c1 agent.sinks = s1 agent.sources.so1.type = avro agent.sources.so1.bind = 0.0.0.0 agent.sources.so1.port = 44444 agent.sources.so1.channels = c1 agent.channels.c1.type = memory agent.channels.c1.capacity = 1000 agent.channels.c1.transactionCapacity = 100 agent.sinks.s1.type = org.riderzen.flume.sink.MongoSink agent.sinks.s1.host = localhost agent.sinks.s1.port = 27017 agent.sinks.s1.model = single agent.sinks.s1.db = test agent.sinks.s1.collection = log agent.sinks.s1.batch = 100 agent.sinks.s1.channel = c1
简单说明:
- 根据agent.sources.so1的相关配置,在44444端口开启监听 - log4j可以往这个端口写日志
- 根据agent.sinks.s1的相关配置,so1接收到的数据,将写到localhost:27017的test数据库的log-collection中
27017是MongoDB的默认监听端口
Java到Flume
文件结构
src/main/java
|---- cn.sinobest.flume.client.demo
|---- LogDemo.java
src/main/resources
|---- log4j.properties
pom.xml
文件内容
- pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.sinobest.asj</groupId> <artifactId>fluent-client-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.apache.flume.flume-ng-clients</groupId> <artifactId>flume-ng-log4jappender</artifactId> <version>1.6.0</version> </dependency> </dependencies> </project>
- log4j.properties
# 配置Log4jAppender,能写日志到Flume log4j.appender.flumeAvro=org.apache.flume.clients.log4jappender.Log4jAppender log4j.appender.flumeAvro.Hostname=localhost log4j.appender.flumeAvro.Port=44444 log4j.appender.flumeAvro.UnsafeMode=true log4j.appender.flumeAvro.layout=org.apache.log4j.PatternLayout log4j.appender.flumeAvro.layout.ConversionPattern=%m # 配置根logger 此配置的日志级别和appender会被所有的logger继承 log4j.rootLogger=INFO, flumeAvro
<1> org.apache.flume.clients.log4jappender.Log4jAppender负责将数据写到Flume的具体实现<2> 44444端口为前文Flume配置agent.sources.so1的监听端口 - LogDemo.java
package cn.sinobest.flume.client.demo; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class LogDemo { static final Log log = LogFactory.getLog(LogDemo.class); public static void main(String[] args) { log.info("{'name':'Adam', 'age':'26', 'skill':'reading'}"); } }
注意:确保日志内容是json格式的字符串。
测试
- 启动MongoDB
D:\develop\MongoDB\bin\mongod --dbpath=D:\develop\MongoDB\mydata
- 启动Flume
# cd F:\temp\apache-flume-1.6.0-bin\bin flume-ng.cmd agent --conf ..\conf -f ..\conf\mongo-agent.properties -n agent
- 运行LogDemo
- 查看结果
D:\tools\PowerCmd>D:\develop\MongoDB\bin\mongo 2016-03-08T18:05:33.168+0800 I CONTROL [main] Hotfix KB2731284 or later update is not installed, will zero-out data files MongoDB shell version: 3.2.3 connecting to: test > db.log.find() { "_id" : ObjectId("56dea2b18449e36553652bc3"), "name" : "Adam", "age" : "26", "skill" : "reading" } >
说明:<1> mongo默认连接test数据库,也可以使用mongo test的方式指定连接test数据库。<2> db.log.find()用来查看log-collection中的数据,可以看到数据已经写入成功。