Flume基礎學習

Hiway發表於2019-09-28

其他更多java基礎文章:
java基礎學習(目錄)


Flume簡介

Flume是一個分散式、可靠、和高可用的海量日誌採集、聚合和傳輸的系統。
支援在日誌系統中定製各類資料傳送方,用於收集資料;
同時,Flume提供對資料進行簡單處理,並寫到各種資料接受方(比如文字、HDFS、Hbase等)的能力。名詞介紹:
Flume OG:Flume original generation,即Flume0.9x版本
Flume NG:Flume next generation,即Flume1.x版本
官網:flume.apache.orgFlume體系結構

Flume體系結構

  1. Flume有一個簡單、靈活的基於流的資料流結構
  2. Flume具有故障轉移機制和負載均衡機制
  3. Flume使用一個簡單可擴充套件的資料模型(source、channel、sink)

目前,flume-ng處理資料有兩種方式:avro-client、agent
avro-client:一次性將資料傳輸到指定的avro服務的客戶端
agent:一個持續傳輸資料的服務

Agent主要的元件包括:SourceChannelSink
Source:完成對日誌資料的手機,分成transtion和event打入到channel之中 Channel:主要提供一個佇列的功能,對source提供的資料進行簡單的快取。
Sink:取出Channel中的資料,進行相應的儲存檔案系統,資料庫或是提交到遠端伺服器。
資料在元件傳輸的單位是Event。

Flume基本元件

Source

source意為來源、源頭。

主要作用

從外界採集各種型別的資料,將資料傳遞給Channel。
比如:監控某個檔案只要增加資料就立即採集新增的資料、監控某個目錄一旦有新檔案產生就採集新檔案的內容、監控某個埠等等。

常見採集的資料型別

Exec Source、Avro Source、NetCat Source、Spooling Directory Source等

詳細檢視:
flume.apache.org/FlumeUserGu… 或者自帶的文件檢視。

Source具體作用:

  • AvroSource:監聽一個avro服務埠,採集Avro資料序列化後的資料;
  • Thrift Source:監聽一個Thrift 服務埠,採集Thrift資料序列化後的資料;
  • Exec Source:基於Unix的command在標準輸出上採集資料;
  • tail -F 和tail -f 區別。基於log4j切割檔案時的能否讀取問題。
  • JMS Source:Java訊息服務資料來源,Java訊息服務是一個與具體平臺無關的API,這是支援jms規範的資料來源採集;
  • Spooling Directory Source:通過資料夾裡的新增的檔案作為資料來源的採集;
  • Kafka Source:從kafka服務中採集資料。
  • NetCat Source: 繫結的埠(tcp、udp),將流經埠的每一個文字行資料作為Event輸入
  • HTTP Source:監聽HTTP POST和 GET產生的資料的採集Channel

Channel

一個資料的儲存池,中間通道。

主要作用

接受source傳出的資料,向sink指定的目的地傳輸。Channel中的資料直到進入到下一個channel中或者進入終端才會被刪除。當sink寫入失敗後,可以自動重寫,不會造成資料丟失,因此很可靠。

channel的型別很多比如:記憶體中、jdbc資料來源中、檔案形式儲存等。

常見採集的資料型別:

Memory Channel
File Channel
Spillable Memory Channel等
詳細檢視: flume.apache.org/FlumeUserGu…

Channel具體作用:

  • Memory Channel:使用記憶體作為資料的儲存。速度快
  • File Channel:使用檔案來作為資料的儲存。安全可靠
  • Spillable Memory Channel:使用記憶體和檔案作為資料的儲存,即:先存在記憶體中,如果記憶體中資料達到閥值則flush到檔案中。
  • JDBC Channel:使用jdbc資料來源來作為資料的儲存。
  • Kafka Channel:使用kafka服務來作為資料的儲存。Sink

Sink:資料的最終的目的地。

主要作用:接受channel寫入的資料以指定的形式表現出來(或儲存或展示)。

sink的表現形式很多比如:列印到控制檯、hdfs上、avro服務中、檔案中等。

常見採集的資料型別:

HDFS Sink、Hive Sink、Logger Sink、Avro Sink、Thrift Sink、File Roll Sink、HBaseSink、Kafka Sink等
詳細檢視:
flume.apache.org/FlumeUserGu…
HDFSSink需要有hdfs的配置檔案和類庫。一般採取多個sink匯聚到一臺採集機器負責推送到hdfs。

Sink具體作用:

  • Logger Sink:將資料作為日誌處理(根據flume中的設定的日誌的級別顯示)。
  • HDFS Sink:將資料傳輸到hdfs叢集中。
  • Avro Sink:資料被轉換成Avro Event,然後傳送到指定的服務埠上。
  • Thrift Sink:資料被轉換成Thrift Event,然後傳送到指定的的服務埠上。
  • File Roll Sink:資料傳輸到本地檔案中。
  • Hive Sink:將資料傳輸到hive的表中。
  • IRC Sink:資料向指定的IRC服務和埠中傳送。
  • Null Sink:取消資料的傳輸,即不傳送到任何目的地。
  • HBaseSink:將資料發往hbase資料庫中。
  • MorphlineSolrSink:資料傳送到Solr搜尋伺服器(叢集)。
  • ElasticSearchSink:資料傳送到Elastic Search搜尋伺服器(叢集)。
  • Kafka Sink:將資料傳送到kafka服務中。(注意依賴類庫)Event

event

event是Flume NG傳輸的資料的基本單位,也是事務的基本單位。
在文字檔案,通常是一行記錄就是一個event。
網路訊息傳輸系統中,一條訊息就是一個event。
event裡有header、body
Event裡面的header型別:Map<String, String>
我們可以在source中自定義header的key:value,在某些channel和sink中使用header。

Flume安裝及簡單例子

Flume安裝

系統要求:

  1. JRE:JDK1.6+(推薦使用1.8)
  2. 記憶體:沒有上限和下限,能夠配置滿足source、channel以及sink即可
  3. 磁碟空間:同2
  4. 目錄許可權:一般的agent操作的目錄必須要有讀寫許可權

安裝步驟:

解壓縮:[uplooking@uplooking01 ~]$ tar -zxvf soft/apache-flume-1.8.0-bin.tar.gz -C app/
重新命名:[uplooking@uplooking01 ~]$ mv app/apache-flume-1.8.0-bin/ app/flume
新增到環境變數中
vim ~/.bash_profile
export FLUME_HOME=/home/uplooking/app/flume
export PATH=$PATH:$FLUME_HOME/bin
修改配置檔案,conf目錄下
cp flume-env.sh.template flume-env.sh
新增JAVA_HOME
export JAVA_HOME=/opt/jdk
複製程式碼

Flume Agent案例偵聽網路埠資料

  1. 定義flume agent配置檔案:
#####################################################################
## this's flume log purpose is listenning a socket port which product
## data of stream
## this agent is consists of source which is r1 , sinks which is k1,
## channel which is c1
##
## 這裡面的a1 是flume一個例項agent的名字
######################################################################定義了當前agent的名字叫做a1
a1.sources = r1 ##定了該agent中的sources元件叫做r1
a1.sinks = k1 ##定了該agent中的sinks元件叫做k1
a1.channels = c1 ##定了該agent中的channels元件叫做c1

# 監聽資料來源的方式,這裡採用監聽網路埠
a1.sources.r1.type = netcat #source的型別為網路位元組流
a1.sources.r1.bind = uplooking01 #source監聽的網路的hostname
a1.sources.r1.port = 52019 #source監聽的網路的port

# 採集的資料的下沉(落地)方式 通過日誌
a1.sinks.k1.type = logger #sink的型別為logger日誌方式,log4j的級別有INFO、Console、file。。。

# 描述channel的部分,使用記憶體做資料的臨時儲存
a1.channels.c1.type = memory #channel的型別使用記憶體進行資料快取,這是最常見的一種channel
a1.channels.c1.capacity = 1000 #定義了channel對的容量
a1.channels.c1.transactionCapacity = 100 #定義channel的最大的事務容量

# 使用channel將source和sink連線起來# 需要將source和sink使用channel連線起來,組成一個類似流水管道
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

複製程式碼
  1. 啟動flume agent:
flume-ng agent -c conf -n a1 -f conf/flume-nc.conf -Dflume.root.logger=INFO,console

-c conf:使用配置檔案的方式-n a1:指定agent的名稱為a1-f:指定配置檔案

因為資料落地是通過日誌,所以後面需要指定日誌的相關配置選項。
複製程式碼
  1. 通過telnet或者nc向埠傳送資料
    安裝telnet或nc:
yum isntall -y telent
yum install -y nc
複製程式碼

向埠傳送資料:

# 使用telnet
[uplooking@uplooking01 ~]$ telnet uplooking01 52019
Trying 192.168.43.101...
Connected to uplooking01.
Escape character is '^]'.
wo ai ni
OK
sai bei de xue
OK

# 使用nc
[uplooking@uplooking01 ~]$ nc uplooking01 52019
heihei
OK
xpleaf
OK
複製程式碼

此時可以檢視flume agent啟動終端的輸出:

2018-03-24 20:09:34,390 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.source.NetcatSource.start(NetcatSource.java:166)] Created serverSocket:sun.nio.ch.ServerSocketChannelImpl[/192.168.43.101:52019]
2018-03-24 20:10:13,022 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 77 6F 20 61 69 20 6E 69 0D wo ai ni. }
2018-03-24 20:10:24,139 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 73 61 69 20 62 65 69 20 64 65 20 78 75 65 0D sai bei de xue. }
2018-03-24 20:13:26,190 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 68 65 69 68 65 69 heihei }
2018-03-24 20:13:26,463 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 78 70 6C 65 61 66 xpleaf }
2018-03-24 20:17:01,694 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 68 65 6C 6C 6F hello }
複製程式碼

偵聽目錄中的新增檔案

配置檔案如下:

####################################################################### 監聽目錄中的新增檔案## this agent is consists of source which is r1 , sinks which is k1,## channel which is c1## ## 這裡面的a1 是flume一個例項agent的名字#####################################################################
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# 監聽資料來源的方式,這裡採用監聽目錄中的新增檔案
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /home/uplooking/data/flume
a1.sources.r1.fileSuffix = .ok
# a1.sources.r1.deletePolicy = immediate
a1.sources.r1.deletePolicy = never
a1.sources.r1.fileHeader = true

# 採集的資料的下沉(落地)方式 通過日誌
a1.sinks.k1.type = logger

# 描述channel的部分,使用記憶體做資料的臨時儲存
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# 使用channel將source和sink連線起來
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
複製程式碼

啟動flume agent:

flume-ng agent -c conf -n a1 -f conf/flume-dir.conf -Dflume.root.logger=INFO,console
複製程式碼

在監聽目錄下新增檔案,內容如下:

hello you
hello he
hello me
複製程式碼

可以看到flume agent終端輸出:

2018-03-24 21:23:59,182 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{file=/home/uplooking/data/flume/hello.txt} body: 68 65 6C 6C 6F 20 79 6F 75 hello you }
2018-03-24 21:23:59,182 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{file=/home/uplooking/data/flume/hello.txt} body: 68 65 6C 6C 6F 20 68 65 hello he }
2018-03-24 21:23:59,182 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{file=/home/uplooking/data/flume/hello.txt} body: 68 65 6C 6C 6F 20 6D 65 hello me }
2018-03-24 21:23:59,184 (pool-3-thread-1) [INFO - org.apache.flume.client.avro.ReliableSpoolingFileEventReader.readEvents(ReliableSpoolingFileEventReader.java:324)] Last read took us just up to a file boundary. Rolling to the next file, if there is one.
2018-03-24 21:23:59,184 (pool-3-thread-1) [INFO - org.apache.flume.client.avro.ReliableSpoolingFileEventReader.rollCurrentFile(ReliableSpoolingFileEventReader.java:433)] Preparing to move file /home/uplooking/data/flume/hello.txt to /home/uplooking/data/flume/hello.txt.ok
複製程式碼

可以看到提示說,原來的文字檔案已經被重新命名為.ok,檢視資料目錄中的檔案:

[uplooking@uplooking01 flume]$ ls
hello.txt.ok
複製程式碼

監聽檔案中的新增資料

tail -f與tail -F的說明:
在生產環境中,為了防止日誌檔案過大,通常會每天生成一個新的日誌檔案, 這是通過重新命名原來的日誌檔案,然後touch一個原來的日誌檔案的方式來實現的。
http-xxx.log
http-xxx.log.2017-03-15
http-xxx.log.2017-03-16
-f不會監聽分割之後的檔案,而-F則會繼續監聽。

配置檔案:

####################################################################### 監聽檔案中的新增資料## ## this agent is consists of source which is r1 , sinks which is k1,## channel which is c1## ## 這裡面的a1 是flume一個例項agent的名字#####################################################################
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# 監聽資料來源的方式,這裡監聽檔案中的新增資料
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /home/uplooking/data/flume/http-flume.log

# 採集的資料的下沉(落地)方式 通過日誌
a1.sinks.k1.type = logger

# 描述channel的部分,使用記憶體做資料的臨時儲存
a1.channels.c1.type = memory
a1.channels.c1.capacity = 10000000
a1.channels.c1.transactionCapacity = 1000000

# 使用channel將source和sink連線起來
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
複製程式碼

啟動flume agent:

flume-ng agent -c conf -n a1 -f conf/flume-data.conf -Dflume.root.logger=INFO,console
複製程式碼

向監聽檔案中新增資料:

cat hello.txt.ok > http-flume.log
複製程式碼

檢視flume agent終端的輸出:

2018-03-25 01:28:39,359 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 68 65 6C 6C 6F 20 79 6F 75 hello you }
2018-03-25 01:28:40,465 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 68 65 6C 6C 6F 20 68 65 hello he }
2018-03-25 01:28:40,465 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.LoggerSink.process(LoggerSink.java:95)] Event: { headers:{} body: 68 65 6C 6C 6F 20 6D 65 hello me }
複製程式碼