参考文章:flume 与 logstash 的比较
一、Logstash
1、Logstash概念
Logstash是一款开源的数据收集引擎,具备实时管道处理能力。简单来说,logstash作为数据源与数据存储分析工具之间的桥梁,结合ElasticSearch以及Kibana,能够极大方便数据的处理与分析。通过200多个插件,logstash可以接受几乎各种各样的数据。包括日志、网络请求、关系型数据库、传感器或物联网等等。
- logstash是一个接收、处理、转发日志的工具,与elasticsearch与kibana同属一个公司,ELK的组合兼容性强。logstash由input、Filter、output三个部分组成。
- input负责数据的输入(产生或搜集,以及解码decode);
- filter负责对采集的日志进行分析,提取字段(一般都是提取关键的字段,存储到elasticsearch中进行检索分析);
- output负责把数据输出到指定的存储位置(kafka、es等)。
2、Logstash工作过程
如上图,Logstash的数据处理过程主要包括:Inputs,Filters,Outputs 三部分,另外在Inputs和Outputs中可以使用Codecs对数据格式进行处理。这四个部分均以插件形式存在,用户通过定义pipeline配置文件,设置需要使用的input,filter,output,codec插件,以实现特定的数据采集,数据处理,数据输出等功能 。
- Inputs:用于从数据源获取数据,常见的插件如file, syslog, redis, beats 等
- Filters:用于处理数据如格式转换,数据派生等,常见的插件如grok, mutate, drop, clone, geoip等
- Outputs:用于数据输出,常见的插件如elastcisearch,file, graphite, statsd等
- Codecs:Codecs(编码插件)不是一个单独的流程,而是在输入和输出等插件中用于数据转换的模块,用于对数据进行编码处理,常见的插件如json,multiline。Logstash不只是一个input | filter | output 的数据流,而是一个 input | decode | filter | encode | output 的数据流!codec 就是用来 decode、encode 事件的。
二、Flume
1、Flume介绍
Apache Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。Flume有两个版本,分别是Flume OG和Flume NG,目前用的都是FlumeNG。
Flume具有高可用,分布式,配置工具,其设计的原理也是基于将数据流,如日志数据从各种网站服务器上汇集起来存储到HDFS,HBase等集中存储器中。
- flume是一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。flume的一个Agent主要由source、channel、sink三个组件组成。
- source负责从数据发生器接收数据;
- channel相当于持久层,用于暂时存储数据;
- sink负责将数据传送到目的地(hdfs、es等)。
- flume支持开发者定制,可以自己进行开发。
2、Flume的外部结构
如上图所示,数据发生器(如:facebook,twitter)产生的数据被服务器上的agent所收集,之后数据收容器从各个agent上汇集数据并将采集到的数据存入到HDFS或者HBase中。
3、Flume事件
事件作为Flume内部数据传输的最基本单元.它是由一个转载数据的字节数组(该数据组是从数据源接入点传入,并传输给传输器,也就是HDFS/HBase)和一个可选头部构成。
典型的Flume 事件如下面结构所示:
Flume agent
对于每一个Agent来说,它就是一共独立的守护进程(JVM),它从客户端哪儿接收收集,或者从其他的Agent哪儿接收,然后迅速的将获取的数据传给下一个目的节点sink,或者agent. 如下图所示flume的基本模型:
Source
从数据发生器接收数据,并将接收的数据以Flume的event格式传递给一个或者多个通道channal,Flume提供多种数据接收的方式,比如Avro,Thrift,twitter1%等。
Channel
channal是一种短暂的存储容器,它将从source处接收到的event格式的数据缓存起来,直到它们被sinks消费掉,它在source和sink间起着一共桥梁的作用,channal是一个完整的事务,这一点保证了数据在收发的时候的一致性.并且它可以和任意数量的source和sink链接. 支持的类型有: JDBC channel , File System channel ,Memort channel等.
Sink
sink将数据存储到集中存储器比如Hbase和HDFS,它从channals消费数据(events)并将其传递给目标地.目标地可能是另一个sink,也可能HDFS,HBase。当Sink写出event成功后,就会向Channel提交事务。Sink事务提交成功,处理完成的event将会被Channel删除。否则Channel会等待Sink重新消费处理失败的event。
Interceptor
拦截器是简单的插件式组件,设置在source和channel之间。source接收到的事件event,在写入channel之前,拦截器都可以进行转换或者删除这些事件。每个拦截器只处理同一个source接收到的事件。可以自定义拦截器。预定义的拦截器包含时间戳拦截器TimestampInterceptor、主机拦截器HostInterceptor、静态拦截器StaticInterceptor、正则过滤拦截器RegexExtractorInterceptor,通过使用不同的拦截器,实现不同的功能。
但是以上的这些拦截器,不能改变原有日志数据的内容或者对日志信息添加一定的处理逻辑,当一条日志信息有几十个甚至上百个字段的时候,在传统的Flume处理下,收集到的日志还是会有对应这么多的字段,也不能对你想要的字段进行对应的处理。根据实际业务的需求,为了更好的满足数据在应用层的处理,通过自定义Flume拦截器,过滤掉不需要的字段,并对指定字段加密处理,将源数据进行预处理。减少了数据的传输量,降低了存储的开销。
三、对比
1、功能上的比较
- Flume偏重数据传输,几乎没有数据的预处理,仅仅是数据的产生,封装成event然后传输。
- Logstash比较偏重于字段的预处理,在异常情况下可能会出现数据丢失,只是在运维日志场景下,一般认为这个可能不重要;
- Logstash的input和filter还有output之间都存在buffer,进行缓冲;Flume直接使用channel做持久化
- 传输方面,flume比logstash多考虑了一些可靠性。因为数据会持久化在channel中(一般有两种可以选择,memoryChannel存在内存中,FileChannel存储在文件中),数据只有存储在下一个存储位置(可能是最终的存储位置,如HDFS;也可能是下一个Flume节点的channel),数据才会从当前的channel中删除。整个过程通过事务控制保证数据的可靠性。
- Flume数据只有sink完成后,才会从当前的channel中删除。这个过程是通过事务控制的,这样就保证了数据的可靠性。但是这里也会产生一个问题:内存如果超过一定的量,也会造成数据丢失;如果使用文件存储,性能会变差。
- logstash比较注重于字段的预处理,logstash有几十个插件,配置灵活。flume则是强调用户的自定义开发(source和sink的种类不多,功能也比较单一)。
- Logstash性能以及资源消耗比较严重,且不支持缓存;
2、操作上的比较
结合实际业务,我简单尝试了一下flume的几种配置:
- flume使用avro source 可以实时读到控制台输出的日志,暂未尝试加上拦截器之后读取速度是否会变慢。需要使用Apache下对应的log包以及配置一个log4j.properties文件:
- flume使用spool source可以读取.log日志文件,但是被读取过的文件会有complete的标记,并不适用现有的日志滚动生成机制。
- flume使用taildir source可以读取指定文件夹下的日志文件,这个是1.8版本中的实验性功能,目前只支持linux系统。
- (原因:taildir会生成一个json文件来记录每个日志的消费偏移量,使得宕机后能从偏移量继续消费,解决数据重复发送的问题,但是这个偏移量在windows系统中无法使用)。
- flume连接es(sink.type = elasticsearch)报错。目前问题定位在flume1.8版本无法连接到es5.4版本。
- (网上给出的解决方案:1、将es版本降低至1.7;2、修改源码)
3、部署的比较
flume与logstash都需要单独安装在服务器上,通过配置文件控制其采集的数据源与数据接收方。
4、现阶段给出的方案
目前logstash存在的问题:
- 读取速度跟不上日志产生速度时会出现数据丢失问题——已有解决方案
- 需要单独安装——flume目前的资料来看也是需要单独安装的
若要使用flume需要:
- 定制source,定义日志过滤的逻辑等,出jar包,放置lib目录下;
- 修改es sink的源码,使其能够连接成功,出jar包,放置lib目录下;
- channel的逻辑是否需要定制、选择内存or文件的持久化方式需结合实际场景。