flume原理及代碼實現

來源:互聯網
上載者:User

標籤:路由   功能   實現原理   lov   部署   pip   run   維護   流轉   

轉載標明出處:http://www.cnblogs.com/adealjason/p/6240122.html

 

最近想玩一下StreamCompute,先看了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原理及代碼實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.