1 Flume簡介
1.1 Flume概述
Flume是Cloudera提供的一個高可用的,高可靠的,分佈式的海量日誌採集、聚合和傳輸的系統。Flume的使用不僅限於日誌數據聚合,由於數據源是可定製的,因此Flume可用於傳輸大量事件數據,包括但不限於網絡流量數據,社交媒體生成的數據,電子郵件消息以及幾乎所有可能的數據源。Flume基於流式架構,靈活簡單。
當前Flume有兩個版本Flume 0.9X版本的統稱Flume-og(Cloudera Flume),Flume1.X版本的統稱Flume-ng(Apache Flume)。由於Flume-ng經過重大重構,與Flume-og有很大不同,使用時請注意區分。
1.2 架構
Flume事件定義爲具有字節有效負載和可選字符串屬性集的數據流單位。Flume Agent是一個(JVM)進程,承載了組件,事件通過這些組件從外部源流到下一個目標(hop)。
外部Source(如Web服務器)以目標Flume Source可以識別的格式將事件發送到Flume。例如,Avro Flume Source可用於從Avro Client或另一個Flume agent的Avro Sink接收Avro事件。可以使用Thrift Flume Source定義類似的流程,以接收來自Thrift Sink或Flume Thrift Rpc客戶端或以Flume Thrift協議生成的任何語言編寫的Thrift客戶端的事件,Flume Source收到事件後,會將其存儲到一個或多個Channel,該Channel是一個被動存儲,用於保留事件,直到被Flume Sink消耗爲止,Sink從通道中刪除事件,並將其放入HDFS之類的外部存儲庫(通過Flume HDFS Sink),或將其轉發到流中下一個Flume Agent的Flume Source。給定Agent中的Source和Sink與通道中上傳的事件異步運行。
1.2.1 Agent
Agent是一個JVM進程,它以事件的形式將數據從源頭送至目的,是Flume數據傳輸的基本單元。Agent主要有3個部分組成,Source、Channel、Sink。 Flume的數據流由事件(Event)貫穿始終。事件是Flume的基本數據單位,它攜帶日誌數據(字節數組形式)並且攜帶有頭信息,這些Event由Agent外部的Source生成,當Source捕獲事件後會進行特定的格式化,然後Source會把事件推入(單個或多個)Channel中。你可以把Channel看作是一個緩衝區,它將保存事件直到Sink處理完該事件。Sink負責持久化日誌或者把事件推向另一個Source。
1.2.2 Source
Source是負責接收數據到Flume Agent的組件。Source組件可以處理各種類型、各種格式的日誌數據。包括:
- Avro Source:RPC框架,接收Avro客戶端的消息
- Thrift Source
- Exec Source:通過Linux命令行獲取數據,如
tail -f
命令 - JMS Source:JMS消息
- Spooling Directory Source:監控某個文件夾內追加的文件
- Taildir Source:監控某個文件夾內文件追加的內容,相對於Exec更好,可以實現斷點續傳
- Twitter 1% firehose Source
- Kafka Source:Kafka消息
- NetCat Source:NetCat支持TCP和UDP,接收NetCat客戶端的消息
- Sequence Generator Source
- Syslog Sources
- Http Source:接收Http消息
- legacy Sources
- Scribe Source
- Custom Source:用戶自定義Source
同一個Source可以關聯多個Channel。
1.2.3 Channel
Channel是位於Source和Sink之間的緩衝區。Channel允許Source和Sink運作在不同的速率上。Channel是線程安全的,可以同時處理幾個Source的寫入操作和幾個Sink的讀取操作。
Flume支持的Channel有:
- Memory Channel:內存中的隊列。在不需要關心數據丟失的情景下適用。如果需要關心數據丟失,那麼Memory Channel就不應該使用,因爲程序死亡、機器宕機或者重啓都會導致數據丟失。
- JDBC Channel
- Kafka Channel
- File Channel:所有事件寫到磁盤。因此在程序關閉或機器宕機的情況下不會丟失數據。
- Spillable Memory Channel
- Pseudo Transaction Channel
- Custom Channel
1.2.4 Sink
Sink不斷地輪詢Channel中的事件且批量地移除它們,並將這些事件批量寫入到存儲或索引系統、或者被髮送到另一個Flume Agent。Sink是完全事務性的。在從Channel批量刪除數據之前,每個Sink用Channel啓動一個事務。批量事件一旦成功寫出到存儲系統或下一個Flume Agent,Sink就利用Channel提交事務。事務一旦被提交,該Channel從自己的內部緩衝區刪除事件。
Flume支持的Sink有:
- HDFS Sink
- Hive Sink
- Logger Sink
- Avro Sink
- Thrift Sink
- IRC Sink
- File Roll Sink
- Null Sink
- HBase Sinks
- MorphlineSolr Sink
- ElasticSearch Sink
- Kite Dataset Sink
- Kafka Sink
- Http Sink
- Custom Sink
1.2.5 Event
傳輸單元, Flume 數據傳輸的基本單元,以 Event 的形式將數據從源頭送至目的地。Event 由 Header 和 Body 兩部分組成, Header 用來存放該 event 的一些屬性,爲 K-V 結構,Body 用來存放該條數據,形式爲字節數組。
1.3 特點
- 複雜流動(Complex flows):支持構建multi-hop流程,事件在到達最終目的地前可通過多個Agent傳遞,同時支持fan-in和fan-out流程,上下文路由和備份路由(故障轉移)。
- 可靠性(Reliability):Flume使用事務性方法來確保事件的可靠傳遞。當節點出現故障時,日誌能夠被傳送到其他節點上而不會丟失。Flume提供了三種級別的可靠性保障,從強到弱依次分別爲:end-to-end(收到數據agent首先將event寫到磁盤上,當數據傳送成功後,再刪除;如果數據發送失敗,可以重新發送。),Store on failure(這也是scribe採用的策略,當數據接收方crash時,將數據寫到本地,待恢復後,繼續發送),Besteffort(數據發送到接收方後,不會進行確認)。
- 可恢復性(Reliability):支持File Channel。
2 數據獲取方式
Flume支持多種機制來從外部源獲取數據。
2.1 RPC
Flume發行版中包含的Avro客戶端可以使用avro RPC機制將給定文件發送到Flume Avro Source
#將/usr/logs/log.10發送到localhost:41414的Avro Source
$ bin/flume-ng avro-client -H localhost -p 41414 -F /usr/logs/log.10
2.2 Exec
exec source執行一個給定的命令並使用輸出。單個“行”輸出(文字後跟回車符(’\ r’)或換行符(’\ n’)或兩者一起)。如:
a2.sources.r2.type = exec
a2.sources.r2.command = tail -F /tmp/root/hive.log
a2.sources.r2.shell = /bin/bash -c
source將通過linux命令去獲取數據
2.3 Network streams
Flume支持以下機制從常用的日誌流類型讀取數據,例如:
- Avro
- Thrift
- Syslog
- Netcat
3 Flume的部署類型
3.1 單一流程(one-agent flow)
3.2 多代理流程(multi-agent flow)
爲了使數據跨多個代理或躍點流動,前一個代理的sink和當前躍點的source需要是avro類型並且sink指向source的主機名(或IP地址)和端口。可以將多個Agent順序連接起來,這是最簡單的情況,一般情況下,應該控制這種順序連接的Agent 的數量,因爲數據流經的路徑變長了,如果不考慮failover的話,出現故障將影響整個Flow上的Agent收集服務。
3.3 流合併(Consolidation)
這種情況應用的場景比較多,比如要收集Web網站的用戶行爲日誌, Web網站爲了可用性使用的負載集羣模式,每個節點都產生用戶行爲日誌,可以爲每 個節點都配置一個Agent來單獨收集日誌數據,然後多個Agent將數據最終匯聚到一個用來存儲數據存儲系統,如HDFS上。
3.4 多路複用流程(Multiplexing the flow)
將多種日誌混合在一起流入一個agent,可以agent中將混雜的日誌流分開,然後給每種日誌建立一個自己的傳輸通道,也可以設置成複製流,每個通道都接收所有的流。
4 快速入門
4.1 安裝部署Flume
- 將
apache-flume-1.9.0-bin.tar.gz
上傳到linux的/opt/software
目錄下 - 解壓
apache-flume-1.9.0-bin.tar.gz
到/opt/module/
目錄下[root@iZnq8v4wpstsagZ software]# tar -zxf apache-flume-1.7.0-bin.tar.gz -C /opt/module/
- 將
apache-flume-1.7.0-bin/conf
下的flume-env.sh.template
文件修改爲flume-env.sh
,並配置flume-env.sh
文件[root@iZnq8v4wpstsagZ conf]# mv flume-env.sh.template flume-env.sh [root@iZnq8v4wpstsagZ conf]# vi flume-env.sh export JAVA_HOME=/opt/module/jdk1.8.0_144
4.2 Flume入門案例
4.2.1 監控端口數據官方案例
需求: 使用 Flume 監聽一個端口, 收集該端口數據,並打印到控制檯。
實現步驟:
- 安裝netcat工具
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# sudo yum install -y nc
- 在
apache-flume-1.9.0-bin
目錄下創建job/flume-netcat-logger.conf
文件夾及文件[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# mkdir job [root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# touch job/flume-netcat-logger.conf
- 編寫
flume-netcat-logger.conf
配置文件[root@iZnq8v4wpstsagZ job]# vim flume-netcat-logger.conf #flume-netcat-logger.conf:單節點Flume配置 #命名Agent a1的組件 a1.sources = r1 a1.sinks = k1 a1.channels = c1 #配置source a1.sources.r1.type = netcat a1.sources.r1.bind = 127.0.0.1 a1.sources.r1.port = 44444 #配置sink a1.sinks.k1.type = logger #緩存事件到Memory Channel a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 #將source和sink綁定到channel a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1
- 運行flume
參數說明:[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# bin/flume-ng agent --conf conf --conf-file job/flume-netcat-logger.conf --name a1 -Dflume.root.logger=INFO,console 或 [root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# bin/flume-ng agent --c conf -f job/flume-netcat-logger.conf -n a1 -Dflume.root.logger=INFO,console
- –conf/-c:表示配置文件存儲在 conf/目錄
- –name/-n:表示給 agent 起名爲 a1
- –conf-file/-f:flume 本次啓動讀取的配置文件是在 job 文件夾下的
flume-netcat-logger.conf
- -Dflume.root.logger=INFO,console :-D 表示 flume 運行時動態修改 flume.root.logger
參數屬性值,並將控制檯日誌打印級別設置爲 INFO 級別。日誌級別包括:log、 info、 warn、
error
- 使用netcat客戶端測試
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# nc -v 127.0.0.1 44444 hello
4.2.2 實時監控單個追加文件
需求: 實時監控 Hive 日誌,並上傳到 HDFS 中。
實現步驟:
- Flume 要想將數據輸出到 HDFS,須持有 Hadoop 相關 jar 包,將以下jar包copy到
/opt/module/apache-flume-1.9.0-bin/lib
目錄下commons-configuration-1.6.jar hadoop-auth-2.7.2.jar hadoop-common-2.7.2.jar hadoop-hdfs-2.7.2.jar commons-io-2.4.jar htrace-core-3.1.0-incubating.jar
- 在
apache-flume-1.9.0-bin/job
目錄下創建flume-file-hdfs.conf
配置文件
對於所有與時間相關的轉義序列, Event Header 中必須存在以 “timestamp”的 key(除非[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# vim job/flume-file-hdfs.conf # Name the components on this agent a2.sources = r2 a2.sinks = k2 a2.channels = c2 # Describe/configure the source a2.sources.r2.type = exec a2.sources.r2.command = tail -F /tmp/root/hive.log a2.sources.r2.shell = /bin/bash -c # Describe the sink a2.sinks.k2.type = hdfs a2.sinks.k2.hdfs.path = hdfs://127.0.0.1:9000/flume/%Y%m%d/%H #上傳文件的前綴 a2.sinks.k2.hdfs.filePrefix = logs- #是否按照時間滾動文件夾 a2.sinks.k2.hdfs.round = true #多少時間單位創建一個新的文件夾 a2.sinks.k2.hdfs.roundValue = 1 #重新定義時間單位 a2.sinks.k2.hdfs.roundUnit = hour #是否使用本地時間戳 a2.sinks.k2.hdfs.useLocalTimeStamp = true #積攢多少個 Event 才 flush 到 HDFS 一次 a2.sinks.k2.hdfs.batchSize = 100 #設置文件類型,可支持壓縮 a2.sinks.k2.hdfs.fileType = DataStream #多久生成一個新的文件 a2.sinks.k2.hdfs.rollInterval = 30 #設置每個文件的滾動大小 a2.sinks.k2.hdfs.rollSize = 134217700 #文件的滾動與 Event 數量無關 a2.sinks.k2.hdfs.rollCount = 0 # Use a channel which buffers events in memory a2.channels.c2.type = memory a2.channels.c2.capacity = 1000 a2.channels.c2.transactionCapacity = 100 # Bind the source and sink to the channel a2.sources.r2.channels = c2 a2.sinks.k2.channel = c2
hdfs.useLocalTimeStamp 設置爲 true,此方法會使用 TimestampInterceptor 自動添加
timestamp)。
a3.sinks.k3.hdfs.useLocalTimeStamp = true - 運行Flume
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# bin/flume-ng agent --conf conf/ --name a2 --conf-file job/flume-file-hdfs.conf
- 運行Hive併產生日誌
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# hive
hive (default)> select * from dept order id;
4.2.3 實時監控目錄下多個新文件
需求: 使用 Flume 監聽整個目錄的文件,並上傳至 HDFS。
實現步驟:
- 在
apache-flume-1.9.0-bin/job
目錄下創建flume-dir-hdfs.conf
配置文件[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# vim job/flume-dir-hdfs.conf a3.sources = r3 a3.sinks = k3 a3.channels = c3 # Describe/configure the source a3.sources.r3.type = spooldir a3.sources.r3.spoolDir = /opt/module/apache-flume-1.9.0-bin/upload a3.sources.r3.fileSuffix = .COMPLETED a3.sources.r3.fileHeader = true #忽略所有以.tmp 結尾的文件,不上傳 a3.sources.r3.ignorePattern = ([^ ]*\.tmp) # Describe the sink a3.sinks.k3.type = hdfs a3.sinks.k3.hdfs.path =hdfs://127.0.0.1:9000/flume/upload/%Y%m%d/%H #上傳文件的前綴 a3.sinks.k3.hdfs.filePrefix = upload- #是否按照時間滾動文件夾 a3.sinks.k3.hdfs.round = true #多少時間單位創建一個新的文件夾 a3.sinks.k3.hdfs.roundValue = 1 #重新定義時間單位 a3.sinks.k3.hdfs.roundUnit = hour #是否使用本地時間戳 a3.sinks.k3.hdfs.useLocalTimeStamp = true #積攢多少個 Event 才 flush 到 HDFS 一次 a3.sinks.k3.hdfs.batchSize = 100 #設置文件類型,可支持壓縮 a3.sinks.k3.hdfs.fileType = DataStream #多久生成一個新的文件 a3.sinks.k3.hdfs.rollInterval = 60 #設置每個文件的滾動大小大概是 128M,略小於block比較好 a3.sinks.k3.hdfs.rollSize = 134217700 #文件的滾動與 Event 數量無關 a3.sinks.k3.hdfs.rollCount = 0 # Use a channel which buffers events in memory a3.channels.c3.type = memory a3.channels.c3.capacity = 1000 a3.channels.c3.transactionCapacity = 100 # Bind the source and sink to the channel a3.sources.r3.channels = c3 a3.sinks.k3.channel = c3
- 運行Flume
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# bin/flume-ng agent --conf conf/ --name a3 --conf-file job/flume-dir-hdfs.conf
- 向 upload 文件夾中添加文件
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# mkdir upload
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# touch upload/test.txt
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# touch upload/test.tmp
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# touch upload/test.log
spooldir Source監控的目錄下文件名不可以重名,不然會導致Flume報錯無法正常運行。不要在監控目錄中創建並持續修改文件,Flume掃描到第一次保存的文件上傳完成後會以.COMPLETED結尾,之後修改將不會觸發事件,被監控文件夾每500ms掃描一次文件變動。
4.2.4 實時監控目錄下的多個追加文件
Exec source 適用於監控一個實時追加的文件, 但不能保證數據不丟失; Spooldir Source 能夠保證數據不丟失,且能夠實現斷點續傳, 但延遲較高,不能實時監控文件改動;而 Taildir Source 既能夠實現斷點續傳,又可以保證數據不丟失,還能夠進行實時監控文件改動。
需求: 使用 Flume 監聽整個目錄的實時追加文件,並上傳至 HDFS。
實現步驟:
- 在
apache-flume-1.9.0-bin/job
目錄下創建flume-taildir-hdfs.conf
配置文件
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# vim job/flume-taildir-hdfs.conf
a4.sources = r4
a4.sinks = k4
a4.channels = c4
# Describe/configure the source
a4.sources.r4.type = TAILDIR
#記錄每個文件的傳輸位置的索引點
a4.sources.r4.positionFile = /opt/module/apache-flume-1.9.0-bin/tail_dir.json
a4.sources.r4.filegroups = f1
a4.sources.r4.filegroups.f1 = /opt/module/apache-flume-1.9.0-bin/files/file.*
# Describe the sink
a4.sinks.k4.type = hdfs
a4.sinks.k4.hdfs.path = hdfs://127.0.0.1:9000/flume/upload/%Y%m%d/%H
#上傳文件的前綴
a4.sinks.k4.hdfs.filePrefix = upload-
#是否按照時間滾動文件夾
a4.sinks.k4.hdfs.round = true
#多少時間單位創建一個新的文件夾
a4.sinks.k4.hdfs.roundValue = 1
#重新定義時間單位
a4.sinks.k4.hdfs.roundUnit = hour
#是否使用本地時間戳
a4.sinks.k4.hdfs.useLocalTimeStamp = true
#積攢多少個 Event 才 flush 到 HDFS 一次
a4.sinks.k4.hdfs.batchSize = 100
#設置文件類型,可支持壓縮
a4.sinks.k4.hdfs.fileType = DataStream
#多久生成一個新的文件
a4.sinks.k4.hdfs.rollInterval = 60
#設置每個文件的滾動大小大概是 128M
a4.sinks.k4.hdfs.rollSize = 134217700
#文件的滾動與 Event 數量無關
a4.sinks.k4.hdfs.rollCount = 0
# Use a channel which buffers events in memory
a4.channels.c4.type = memory
a4.channels.c4.capacity = 1000
a4.channels.c4.transactionCapacity = 100
# Bind the source and sink to the channel
a4.sources.r4.channels = c4
a4.sinks.k4.channel = c4
- 運行Flume
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# bin/flume-ng agent --conf conf/ --name a4 --conf-file job/flume-taildir-hdfs.conf
- 向 files 文件夾中追加內容
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# mkdir files
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# echo hello >> file1.txt
[root@iZnq8v4wpstsagZ apache-flume-1.9.0-bin]# echo world >> file2.txt
Taildir Source 維護了一個 json 格式的 position File,其會定期的往 position File中更新每個文件讀取到的最新的位置,因此能夠實現斷點續傳。Position File 的格式如下:
{"inode":2496272,"pos":12,"file":"/opt/module/apache-flume-1.9.0-bin/files/file1.txt"}
{"inode":2496275,"pos":12,"file":"/opt/module/apache-flume-1.9.0-bin/files/file2.txt"}
Linux 中儲存文件元數據的區域就叫做 inode, 每個 inode 都有一個號碼,操作系統用 inode 號碼來識別不同的文件, Unix/Linux 系統內部不使用文件名,而使用 inode號碼來識別文件
4.3 在配置文件中使用環境變量
Flume可以替換配置中值的環境變量,如:
a1.sources = r1
a1.sources.r1.type = netcat
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = ${NC_PORT}
a1.sources.r1.channels = c1
可以通過代理調用上的Java系統屬性來啓用,如:
NC_PORT=44444 bin/flume-ng agent -c conf/ -f job/netcat-flume-logger.conf -n a1 -Dflume.root.logger=INFO,console -DpropertiesImplementation=org.apache.flume.node.EnvVarResolverProperties
也可以用其他方式配置環境變量,包括在conf/flume-env.sh
中設置
4.4 第三方插件
Flume具有完全基於插件的體系結構。Flume擁有很多開箱即用的sources、channels、sinks、serializers,並且提供許多與Flume解耦的實現方案。雖然Flume可以通過在flume-env.sh
文件添加用戶自定義的Flume組件jars到FLUME_CLASSPATH
中,但Flume支持在$FLUME_HOME/plugins.d
目錄下自動獲取特定格式打包的插件,這使插件的管理更加容易。
每個插件目錄在plugins.d
目錄下最多可以有三個子目錄:
- lib:插件的jar(s)
- libext:該插件的依賴jar(s)
- native:任何所需的本地庫,如的.so文件