概要
Apache Flume 是一個分布式痴腌,可靠且可用的系統(tǒng)搬味,用于有效地從許多不同的源收集期奔、聚合和移動大量日志數(shù)據(jù)到一個集中式的數(shù)據(jù)存儲區(qū)臼膏。
Flume 的使用不只限于日志數(shù)據(jù)。因為數(shù)據(jù)源可以定制张症,flume 可以被用來傳輸大量事件數(shù)據(jù)仓技,這些數(shù)據(jù)不僅僅包括網(wǎng)絡通訊數(shù)據(jù)、社交媒體產(chǎn)生的數(shù)據(jù)俗他、電子郵件信息等等脖捻。
Apache Flume 是 Apache 基金會的頂級項目,在加入 Apache 之前由 cloudera 公司開發(fā)以及維護兆衅。
Apache Flume 目前有兩種主版本: 0.9.x 和 1.x地沮。 其中 0.9.x 是歷史版本,我們稱之為 Flume OG(original generation)羡亩。2011 年 10 月 22 號摩疑,cloudera 完成了 Flume-728,對 Flume 進行了里程碑式的改動:重構核心組件畏铆、核心配置以及代碼架構雷袋,重構后的版本統(tǒng)稱為 Flume NG(next generation),也就是這里說的 1.x 版本辞居。
本文主要對 Flume 的作用以及核心概念進行介紹楷怒,通過本文讀者可以大致了解 flume 的使用場景、核心組件以及各組件的運行機制瓦灶。關于如何配置 flume 以適應不同場景鸠删,我們會在另一篇文章中詳細解讀。
架構
數(shù)據(jù)流模型
一個 Flume 事件被定義為一個數(shù)據(jù)流單元贼陶。Flume agent 其實是一個 JVM 進程刃泡,該進程中包含完成任務所需要的各個組件,其中最核心的三個組件是 Source碉怔、Chanel 以及 Slink烘贴。

Source 消費由外部源(如Web服務器)傳遞給它的事件。外部源以一定的格式發(fā)送數(shù)據(jù)給 Flume撮胧,這個格式的定義由目標 Flume Source 來確定桨踪。例如,一個 Avro Flume source 可以從 Avro(Avro是一個基于二進制數(shù)據(jù)傳輸?shù)母咝阅苤虚g件趴樱,是 hadoop 的一個子項目) 客戶端接收 Avro 事件馒闷,也可以從其他 Flume agents (該 Flume agents 有 Avro sink)接收 Avro 事件。 同樣叁征,我們可以定義一個 Thrift Flume Source 接收來自 Thrift Sink纳账、Flume Thrift RPC 客戶端或者其他任意客戶端(該客戶端可以使用任何語言編寫,只要滿足 Flume thrift 協(xié)議)的事件捺疼。
channel 可以理解為緩存區(qū)疏虫,用來保存從 Source 那拿到的數(shù)據(jù),直到 Flume slink 將數(shù)據(jù)消費啤呼。file chanel 是一個例子卧秘,它將數(shù)據(jù)保存在文件系統(tǒng)中(當然你可以將數(shù)據(jù)放在內(nèi)存中)。
slink 從 channel 消費完數(shù)據(jù)就會將數(shù)據(jù)從 channel 中清除官扣,隨后將數(shù)據(jù)放到外部存儲系統(tǒng)例如 HDFS (使用 Flume HDFS sink)或發(fā)送到其他 Flume agent 的 source 中翅敌。不管是 Source 還是 Slink 都是異步發(fā)送和消費數(shù)據(jù)。
復雜的流
Flume 允許用戶構建一個復雜的數(shù)據(jù)流惕蹄,比如數(shù)據(jù)流經(jīng)多個 agent 最終落地蚯涮。It also allows fan-in and fan-out flows, contextual routing and backup routes (fail-over) for failed hops.
可靠性
事件被存儲在每個 agent 的 channel 中。隨后這些事件會發(fā)送到流中的下一個 agent 或者設備存儲中(例如 HDFS)卖陵。只有事件已經(jīng)被存儲在下一個 agent 的 channel 中 或設備存儲中時遭顶,當前 channel 才會清除該事件。這種機制保證了流在端到端的傳輸中具有可靠性泪蔫。
Flume使用事務方法(transactional approach)來保證事件的可靠傳輸棒旗。在 source 和 slink 中,事件的存儲以及恢復作為事務進行封裝撩荣,存放事件到 channel 中以及從 channel 中拉取事件均是事務性的铣揉。這保證了流中的事件在節(jié)點之間傳輸是可靠的。
可恢復
事件在 channel 中進行婿滓,該 channel 負責保障事件從故障中恢復老速。Flume 支持一個由本地文件系統(tǒng)支持的持久化文件(文件模式:channel.type = "file") channel。同樣也支持內(nèi)存模式(channel.type = "memmory"),即將事件保存在內(nèi)存隊列中凸主。顯然橘券,內(nèi)存模式相對與文件模型性能會更好,但是當 agent 進程不幸掛掉時卿吐,內(nèi)存模式下存儲在 channel 中的事件將丟失旁舰,無法進行恢復。
構建
構建一個 agent
Flume agent 的配置保存在一個本地配置文件中嗡官。它是一個 text 文本箭窜,java 程序可以直接方便地讀取其屬性⊙苄龋可以在同一配置文件中指定一個或多個 agent 的配置磺樱。配置文件指定了 agnet 中每個 source纳猫、channel、slink 的屬性竹捉,以及三者如何組合形成數(shù)據(jù)流芜辕。
配置單個組件
流中的每一個組件(source、channel块差、slink)都有自己的名稱侵续、類型以及一系列配置屬性。例如憨闰,一個 Avro source 需要配置 hostname (或者 IP 地址)以及端口號來接收數(shù)據(jù)状蜗。一個內(nèi)存模式 channel 可以有最大隊列長度的屬性("capacity": channel 中最大容納多少事件)。一個 HDFS slink 則需要知道文件系統(tǒng)的 URL(hdfs://****)鹉动、文件落地的路徑轧坎、文件回滾的評率("hdfs.rollInterval": 每隔多少秒將零時文件回滾成最終文件保存到 HDFS 中)。所有這些關于各個組件的屬性需要在配置文件中進行指定训裆。
將各個部分組合起來
Agent 需要知道加載哪些組件以及如何將這些組件組合起來形成數(shù)據(jù)流眶根。Flume 指定每個組件的名稱(source、channel边琉、slink)属百,同時明確地告訴我們 channel 與 哪些 source 和 slink 連接,這樣各個組件就能組合起來变姨。例如族扰,一個叫 "avroWeb" 的 source 通過一個叫 "file-channel" 的channel 將事件傳遞到 HDFS sink 中。配置文件需包含這些組件的名稱以及組合關系定欧。
開始一個 agent
我們可以通過 Flume bin 目錄下的腳本文件(flume-ng)來啟動 agent渔呵。在命令后面,你需要指定 agent 的名稱砍鸠、配置文件:
$ bin/flume-ng agent -n $agent_name -c conf -f conf/flume-conf.properties.template
運行以上命令扩氢,agent 將會按照配置文件里描述的方式來運行組件。
一個簡單的示例
這里爷辱,我們給出一個配置文件的示例录豺,該示例為 flume 單節(jié)點部署的配置方式。
# example.conf: A single-node Flume configuration
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444
# Describe the sink
a1.sinks.k1.type = logger
# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
看看這個配置文件饭弓,我們可以發(fā)現(xiàn)這個 agent 的名稱是 a1双饥。其中該 agent 的 source 監(jiān)聽 44444 端口。channel 采用內(nèi)存模式弟断,而 slink 直接輸出數(shù)據(jù)到 控制臺上(logger)咏花。配置文件指定了各個組件的名稱,并描述了它們的類型以及其他屬性阀趴。當然昏翰,一個配置文件可以配置多個 agent 屬性苍匆,當希望運行指定 agent 進程時,我們需要在命令行中顯示的給出該 agent 的名稱:
$ bin/flume-ng agent --conf conf --conf-file example.conf --name a1 -Dflume.root.logger=INFO,console
注意棚菊,在實際部署中锉桑,我們通常會包含一個選項: --conf-file = <conf-dir>。 <conf-dir> 目錄將包含一個 shell 腳本 flume-env.sh 以及一個 log4j 屬性文件窍株。 在這個例子中,我們傳遞一個 Java 選項來強制 Flume 將日志輸出到控制臺攻柠。
下面的例子中球订,我們可以遠程 telnet 訪問 44444 端口來向 agent 發(fā)送數(shù)據(jù):
$ telnet localhost 44444
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
Hello world! <ENTER>
OK
agent 進程的控制臺將會打印通過 telnet 發(fā)送的數(shù)據(jù):
12/06/19 15:32:19 INFO source.NetcatSource: Source starting
12/06/19 15:32:19 INFO source.NetcatSource: Created serverSocket:sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:44444]
12/06/19 15:32:34 INFO sink.LoggerSink: Event: { headers:{} body: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 0D Hello world!. }
完成這一步,恭喜你已經(jīng)成功地配置以及部署一個 flume agent瑰钮。
數(shù)據(jù)獲让疤病(Data ingestion)
Flume 支持許多從外部源獲取數(shù)據(jù)的機制。
RPC
一個 Avro client 可以使用 rpc 機制發(fā)送指定的文件到 source 中:
$ bin/flume-ng avro-client -H localhost -p 41414 -F /usr/logs/log.10
上面的命令會將 /usr/logs/log.10 發(fā)送到監(jiān)聽 41414 端口的 source 上浪谴。
網(wǎng)絡流(Network streams)
Flume 支持從一些流行的日志流中讀取數(shù)據(jù)开睡,例如:
- Avro
- Thrift
- Syslog
- Netcat
設置多 agent 流(Setting multi-agent flow)

Flume 支持將多個 agent 串聯(lián)起來,完成這項操作苟耻。
合并(Consolidation)
當需要從眾多主機上收集日志信息時篇恒,我們可以在每臺主機上部署 agent,這些主機的 slink 均連接到最終日志落地主機的 source 上。落地主機將所有數(shù)據(jù)進行組合凶杖,落地到 HDFS 上胁艰。

