转载标明出处:http://www.cnblogs.com/adealjason/p/6240122.html

最近想玩一下流计算,先看了flume的实现原理及源码

源码可以去apache 官网下载

下面整理下flume的原理及代码实现:

flume是一个实时数据收集工具,hadoop的生态圈之一,主要用来在分布式环境下各服务器节点做数据收集,然后汇总到统一的数据存储平台,flume支持多种部署架构模式,单点agent部署,分层架构模式部署,如通过一个负载均衡agent将收集的数据分发到各个子agent,然后在汇总到同一个agent上,数据传输到统一的数据存储平台,再次不多废话,flume支持的部署架构图可以参见源码中的doc目录下的图片

flume原理:

目前最新版本是Flume NG,以下基于Flume NG来说:

flume由以下几个核心概念:

flume event:flume内部的数据单元,包含两部分,一个头结点,一个body结点,头结点是一个Map<String, String>,部署的agent结点可以通过现有的Interceptor或者自定义Interceptor往消息头里放置数据,如ip,hostname等标识消息来源于哪台服务器,event在flume内部做流转,是数据传输的载体

flume source:source是flume的数据来源,flume支持多种数据来源,如taildir监控一个文件的变化,spollDir监控一个文件夹的变化,jmsSource接收jms消息等,最常用的avroSource是构成flume分层架构的基础,source是一个接口,flume提供了多种消息接入方式,在sourceType枚举类中都有详细列出,特殊说明下,由于flume是面向接口编程,其中有一个Other的枚举,是占位符,使用者可以自定义source源,只要求在flume启动的时候可以加载到这个类即可(底层是通过反射获取到class的实例的)

flume channel:flume是基于pipeline的模式,channel的存在丰富了flume的数据传播途径,channel可以再source和sink之间做缓冲,动态调节数据的收集及发送(内部有一个xxxCounter会没接收到一个event或者发送一个event都会做记录),缓冲source和sink之间的压力,其二channel可以关联多个source,如一个source可以按照配置选择的将数据复制到各个管道,或者按照消息头自动分发到指定的管道,一个channel可以接多个sink,这个实现了同一份数据的多发发送池,实现了数据的复用及负载均衡等功能,channel内部流转的数据载体是event,flume channel支持多种数据缓冲实现方式,如fileChannel:用一个文件做数据缓存、memoryChannel:使用内存缓存,底层实现是一个LinkedBlockingDeque,一个双向阻塞列表,具体可参见ChannelType

flume sink:flume的数据发送池,主要负责数据的发送,从channel接收到event,然后发送到指定的数据接收方,flume提供多种sink实现,具体可参见SinkType,常用的有:loggerSink:这个主要用于flume的部署调试,它会将接收到的event事件直接用log4j输出出来,RollingFileSink:这个sink主要是将接收到的日志文件序列化到一个文件目录中,所以需要配置文件的地址,切分文件的频率等,avroSink:这个是flume分层架构中最常用的sink,一般和avroSource配对使用,avro是apache的一个子项目,用于数据的序列化,使用avroSource及avroSink时,需要在avroSource的agent节点服务器上监听一个端口,avroSink的agent把接收到的数据发送到该ip、port上即完成了flume的分层部署,avro仅是一个数据序列化工具,底层实现由一个RpcClient的东东来将数据在这source和sink之间传输(可以留一下启动日志,会自动创建一个RpcClient),当然,flume的编码是按照面向接口来的,所以和source一样支持自定义的sink

上述是几个核心的概念,正式由于flume的这种设计思想及编码风格,让flume有很强的拓展性

当然仅仅有这几个还是不可以完全让flume运行起来的,flume提供了很多辅助类用于驱动、分发内部event及整个flume系统的运转,基本如下:

配置领域:

AgentConfiguration:这个看名字就知道是flume的配置元素领域内的东西,是的,使用者在flume-conf.properties中配置的数据解析成AgentConfiguration,是配置文件到面向对象的一个抽象

AbstractConfigurationProvider:该类看名字就是一个抽象的配置Provider类,内部有一个很重要的方法就是:getConfiguration(),该方法中通过如下几个private方法来加载flume的channel、source、sink、sinkGroups并将它们关联起来

loadChannels(agentConf, channelComponentMap);

loadSources(agentConf, channelComponentMap, sourceRunnerMap);

loadSinks(agentConf, channelComponentMap, sinkRunnerMap);

flume还支持动态加载,PollingPropertiesFileConfigurationProvider(AbstractConfigurationProvider的一个具体实现)在flume启动的时候会启动一个线程FileWatcherRunnable,监控flume的配置文件变化,配置文件内部加载用的是google的EventBus来驱动的

驱动领域:

flume的source有如下两个子接口:PollableSource和EventDrivenSource,前者需要自己去轮循的访问数据源,当前是否可以加载到数据,如果有则加载进来转换成flume的event,实现类有taildir、spollDir、jsmSource、kafkaSource等,该接口新增了一个process方法用于轮循调用,后者是一个事件驱动的Source,该接口不需要主动去访问数据源,仅需要接收数据推动过来的event并转换成flume的event即可,实现类有:scribeSource(该数据源用来打通Facebook的scribe数据收集工具)、AvroSource等

SourceRunner:

由于这两个source的存在,所以所以flume提供了两个sourceRunner来驱动source的运行,分别是PollableSourceRunner和EventDrivenSourceRunner,前者启动时自动启动一个PollingRunner线程用于定时轮循process方法

channelProcessor:

该类用于source到channel之间的数据发送,实现了一个source可以关联到多个channel,简单点如这2个接口,source的定义:setChannelProcessor(ChannelProcessor channelProcessor)指定一个ChannelProcessor ,ChannelProcessor 关联到一个final的ChannelSelector,selector关联到Channel:setChannels(List<Channel> channels)

ChannelProcessor:

关联到指定的ChannelSelector,ChannelSelector提供了两种selector方式,ReplicatingChannelSelector:将source的event复制到各个channel中,MultiplexingChannelSelector:根据头结点的header信息自动路由到对应的Channel中

Transaction及BasicTransactionSemantics

flume的Channel内部保证一个event的发送在一个事务完成,如果发送失败或者接收失败则回滚,当成功时才从channel中删除掉该event

SinkProcessor:

用过选择要发送的sink,什么意思呢?该类有两个实现:

LoadBalancingSinkProcessor:

负载均衡方式:提供了roud_bin算法和random算法、以及固定order算法的实现方式,将Channel中的event发送到多个sink上

FailoverSinkProcessor:

可以实现实现failover功能,具体流程类似LoadBalancingSinkProcessor,区别是FailoverSinkProcessor维护了一个PriorityQueue,用来根据权重选择sink

SinkRunner:

该类用于驱动一个sink,启动是内部开了一个线程PollingRunner,定时的调用SinkProcessor

上述是所有的核心概念及代码作用,下面描述下flume的运行流程:

1.系统启动时通过配置领域可以按照客户定义的配置加载一个flume

2.SourceRunner和SinkProcessor同时启动,一个往Channel中生产event,一个从Channel中消费event,内部是一个生产者消费者模式

3.通过一些辅助类,实现Channel到source及sink的多路分发及分层架构

下面是一个自己搭建的flume配置文件,供参考:

实现流程:

负载均衡+分发+落地到日志文件

1.负载均衡节点:

从两个文件源读数据,在event头里增加数据来源标识,复制到两个channel中,一个log打印,一个做负载均衡分发到另外两台机器的agent上,负载均衡算法采用roud_robin

loadBalancAgent.sources = taildirSrc

loadBalancAgent.channels = memoryChannel fileChannel

loadBalancAgent.sinks = loggerSink1 loggerSink2 loggerSink3

loadBalancAgent.sinkgroups = loadBalanceGroups

## taildirSrc config

loadBalancAgent.sources.taildirSrc.type = TAILDIR

loadBalancAgent.sources.taildirSrc.positionFile = /alidata1/admin/openSystem/flumetest/log/taildir_position.json

loadBalancAgent.sources.taildirSrc.filegroups = f1 f2

loadBalancAgent.sources.taildirSrc.filegroups.f1 = /alidata1/admin/dts-server-web/dts-server.log

loadBalancAgent.sources.taildirSrc.headers.f1.headerKey1 = dts-server-log

loadBalancAgent.sources.taildirSrc.filegroups.f2 = /alidata1/admin/flume/test.log

loadBalancAgent.sources.taildirSrc.headers.f2.headerKey1 = flume-test-log

loadBalancAgent.sources.taildirSrc.fileHeader = true

## replicating channel config

loadBalancAgent.sources.taildirSrc.selector.type = replicating

loadBalancAgent.sources.taildirSrc.channels = memoryChannel fileChannel

loadBalancAgent.sources.taildirSrc.selector.optional = fileChannel

## memory chanel config

loadBalancAgent.channels.memoryChannel.type = memory

loadBalancAgent.channels.memoryChannel.capacity = 10000

loadBalancAgent.channels.memoryChannel.transactionCapacity = 10000

loadBalancAgent.channels.memoryChannel.byteCapacityBufferPercentage = 20

loadBalancAgent.channels.memoryChannel.byteCapacity = 800000

## file channel config

loadBalancAgent.channels.fileChannel.type = file

loadBalancAgent.channels.fileChannel.checkpointDir = /alidata1/admin/openSystem/flumetest/log

loadBalancAgent.channels.fileChannel.dataDirs = /alidata1/admin/openSystem/flumetest/data

## loadbalance sink processor

loadBalancAgent.sinkgroups.loadBalanceGroups.sinks = loggerSink1 loggerSink2

loadBalancAgent.sinkgroups.loadBalanceGroups.processor.type = load_balance

loadBalancAgent.sinkgroups.loadBalanceGroups.processor.backoff = true

loadBalancAgent.sinkgroups.loadBalanceGroups.processor.selector = round_robin

## loggerSink1 config

loadBalancAgent.sinks.loggerSink1.type = avro

loadBalancAgent.sinks.loggerSink1.channel = memoryChannel

loadBalancAgent.sinks.loggerSink1.hostname = 10.253.42.162

loadBalancAgent.sinks.loggerSink1.port = 4141

## loggerSink2 config

loadBalancAgent.sinks.loggerSink2.type = avro

loadBalancAgent.sinks.loggerSink2.channel = memoryChannel

loadBalancAgent.sinks.loggerSink2.hostname = 10.139.53.6

loadBalancAgent.sinks.loggerSink2.port = 4141

## loggerSink3 config

loadBalancAgent.sinks.loggerSink3.type = file_roll

loadBalancAgent.sinks.loggerSink3.channel = fileChannel

loadBalancAgent.sinks.loggerSink3.sink.rollInterval = 0

loadBalancAgent.sinks.loggerSink3.sink.directory = /alidata1/admin/openSystem/flumetest/dtsServerLog

2.负载均衡节点1

接收avroSink并落地到文件中

dispatchAgent.sources= avroSrc

dispatchAgent.channels=memoryChannel

dispatchAgent.sinks=loggerSink

## avroSrc config

dispatchAgent.sources.avroSrc.type = avro

dispatchAgent.sources.avroSrc.channels = memoryChannel

dispatchAgent.sources.avroSrc.bind = 0.0.0.0

dispatchAgent.sources.avroSrc.port = 4141

## memoryChannel config

dispatchAgent.channels.memoryChannel.type = memory

dispatchAgent.channels.memoryChannel.capacity = 10000

dispatchAgent.channels.memoryChannel.transactionCapacity = 10000

dispatchAgent.channels.memoryChannel.byteCapacityBufferPercentage = 20

dispatchAgent.channels.memoryChannel.byteCapacity = 800000

## loggerSink config

dispatchAgent.sinks.loggerSink.type = logger

dispatchAgent.sinks.loggerSink.channel = memoryChannel

3.负载均衡节点2

dispatchAgent.sources= avroSrc

dispatchAgent.channels=memoryChannel

dispatchAgent.sinks=loggerSink

## avroSrc config

dispatchAgent.sources.avroSrc.type = avro

dispatchAgent.sources.avroSrc.channels = memoryChannel

dispatchAgent.sources.avroSrc.bind = 0.0.0.0

dispatchAgent.sources.avroSrc.port = 4141

## memoryChannel config

dispatchAgent.channels.memoryChannel.type = memory

dispatchAgent.channels.memoryChannel.capacity = 10000

dispatchAgent.channels.memoryChannel.transactionCapacity = 10000

dispatchAgent.channels.memoryChannel.byteCapacityBufferPercentage = 20

dispatchAgent.channels.memoryChannel.byteCapacity = 800000

## loggerSink config

dispatchAgent.sinks.loggerSink.type = logger

dispatchAgent.sinks.loggerSink.channel = memoryChannel

flume原理及代码实现的更多相关文章

  1. Java Base64加密、解密原理Java代码

    Java Base64加密.解密原理Java代码 转自:http://blog.csdn.net/songylwq/article/details/7578905 Base64是什么: Base64是 ...

  2. Base64加密解密原理以及代码实现(VC++)

    Base64加密解密原理以及代码实现 转自:http://blog.csdn.net/jacky_dai/article/details/4698461 1. Base64使用A--Z,a--z,0- ...

  3. AC-BM算法原理与代码实现(模式匹配)

    AC-BM算法原理与代码实现(模式匹配) AC-BM算法将待匹配的字符串集合转换为一个类似于Aho-Corasick算法的树状有限状态自动机,但构建时不是基于字符串的后缀而是前缀.匹配 时,采取自后向 ...

  4. Java基础知识强化之集合框架笔记47:Set集合之TreeSet保证元素唯一性和比较器排序的原理及代码实现(比较器排序:Comparator)

    1. 比较器排序(定制排序) 前面我们说到的TreeSet的自然排序是根据集合元素的大小,TreeSet将它们以升序排列. 但是如果需要实现定制排序,比如实现降序排序,则要通过比较器排序(定制排序)实 ...

  5. PHP网站安装程序的原理及代码

    原文:PHP网站安装程序的原理及代码 原理: 其实PHP程序的安装原理无非就是将数据库结构和内容导入到相应的数据库中,从这个过程中重新配置连接数据库的参数和文件,为了保证不被别人恶意使用安装文件,当安 ...

  6. 免费的Lucene 原理与代码分析完整版下载

    Lucene是一个基于Java的高效的全文检索库.那么什么是全文检索,为什么需要全文检索?目前人们生活中出现的数据总的来说分为两类:结构化数据和非结构化数据.很容易理解,结构化数据是有固定格式和结构的 ...

  7. 机器学习之KNN原理与代码实现

    KNN原理与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/9670187.html 1. KNN原理 K ...

  8. 机器学习之AdaBoost原理与代码实现

    AdaBoost原理与代码实现 本文系作者原创,转载请注明出处: https://www.cnblogs.com/further-further-further/p/9642899.html 基本思路 ...

  9. 机器学习之决策树三-CART原理与代码实现

    决策树系列三—CART原理与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/9482885.html ID ...

随机推荐

  1. CentOS 6.5下Zabbix的安装配置

    1.确保开发环境lamp已经安装 2.下载zabbix 官方下载地址:http://www.zabbix.com/download.php 选择和自己系统对应的版本,这里选择安装与Linux内核为2. ...

  2. caffe学习笔记(一),ubuntu14.04+GPU (用Pascal VOC2007训练数据,并测试)

    把源代码跑起来了,将实验过程记录如下,用于新手入门. 今天和师兄师姐才跑通,来分享下心得.(预训练网络:ImageNet_model,训练集:PASCAL VOC2007, GPU) 首先,整个tra ...

  3. Android判断网路是否畅通加权限

    权限 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission ...

  4. java第六次作业(老师讲过后)

    import java.util.*; public class Draw { private ArrayList list; public Draw() { list= new ArrayList( ...

  5. JAG Summer 2012 Day 4 C Connect

    状压dp,由于枚举两维状态会GG,所以只枚举当前位置前m个的状态,就是这个样子大概= =: 呆马: #include <iostream> #include <cstdio> ...

  6. C#中常用的转义字符及@符号的一些作用

    转义符指的就是一个'\'+一个特殊的字符,组成了一个具有特殊意义的字符. \n:表示换行.  /b表示一个退格键.放到字符串两边没有效果. \t:表示tab键的空格 \":表示一个英文半角的 ...

  7. 利用python检测色情图片简易实例

    import sys import os import _io from collections import namedtuple from PIL import Image class Nude( ...

  8. iOS开发中设置UITextField的占位文字的颜色,和光标的颜色

    在iOS开发中,对于很多初学者而言,很有可能碰到需要修改UITextField的占位文字的颜色,以及当UITextField成为第一响应者后光标的颜色,那么下面小编就介绍一下修改占位文字和光标的颜色. ...

  9. 初学者-微信小程序 问题解决办法记录

    1.tabBar不显示的问题 1),检查大小写 2),pagePath路径书写,和pages路径一样,不能多或者少一个"/"或者"?" 2.tabBar和nav ...

  10. Android Studio 自定义debug签名文件keystore

    Android Studio 自定义debug签名文件keystore