面對(duì)以上的問(wèn)題,我們?nèi)绾螌⑦@些日志移動(dòng)到hdfs集群上尼导饲???渣锦?
第一種方案:使用shell腳本cp 文件硝岗,然后通過(guò)hdfs fs -put 源文件? hdfs目錄。
此方案可行袋毙,但是優(yōu)缺點(diǎn):如下
1)缺乏監(jiān)控機(jī)制型檀、如果某臺(tái)日志服務(wù)器宕機(jī)了怎么辦?
2)如果使用腳本听盖,肯定要對(duì)腳本做定時(shí)觸發(fā)的機(jī)制胀溺,每隔一分鐘或者兩分鐘,這個(gè)時(shí)效性就會(huì)打折扣
3)文件都是存放在服務(wù)器磁盤(pán)上的皆看,如果要移動(dòng)日志文件仓坞,肯定會(huì)產(chǎn)生較大的磁盤(pán)IO,必須要壓縮傳輸
4)業(yè)務(wù)服務(wù)器一般都是多節(jié)點(diǎn)部署的腰吟,肯定會(huì)產(chǎn)生多份日志文件无埃,如何把這些日志聚合在一起?
因此這時(shí)候就出現(xiàn)了一個(gè)較為可靠的解決方案Flume框架
Flume概述
官網(wǎng)地址:http://flume.apache.org/
介紹:他就是把我們的日志毛雇,從a地方搬運(yùn)到b地方的服務(wù)框架
Source:收集
詳細(xì)介紹:http://flume.apache.org/releases/content/1.9.0/FlumeUserGuide.html#flume-sources
Channel:相當(dāng)于通道灵疮,是數(shù)據(jù)臨時(shí)存放的地方织阅,聚合、緩沖區(qū)
詳細(xì)介紹:http://flume.apache.org/releases/content/1.9.0/FlumeUserGuide.html#flume-sources
Sink:輸出
詳細(xì)介紹:http://flume.apache.org/releases/content/1.9.0/FlumeUserGuide.html#flume-sources
Flume三種流行的使用方案
第一種:
第二種:(最常用的)
第三種:
Flume部署
前置條件:
1)Java Runtime Environment - Java 1.8 or later
2)Memory - Sufficient memory for configurations used by sources, channels or sinks
3)Disk Space - Sufficient disk space for configurations used by channels or sinks
4)Directory Permissions - Read/Write permissions for directories used by agent
第一步:
下載jdk
安裝jdk
配置環(huán)境變量
第二步:
下載flume震捣,地址為http://archive.cloudera.com/cdh5/cdh/5/
weget?http://archive.cloudera.com/cdh5/cdh/5/flume-ng-1.6.0-cdh5.7.0.tar.gz
解壓:tar -zvxf? flume-ng-1.6.0-cdh5.7.0.tar.gz? -C ~/usr/目錄下
配置環(huán)境變量:
1荔棉、vim /etc/profile
export FLUME_HOME=/usr/apache-flume-1.6.0-cdh5.7.0-bin
export PATH=$PATH:$FLUME_HOME/bin
2、//使環(huán)境變量配置生效
source /etc/profile
3伍派、配置flume根目錄中conf目錄中文件flume-env.sh的配置參數(shù)江耀,復(fù)制flume-env.sh.template成flume-env.sh在flume-env.sh中設(shè)置flume依賴(lài)的jdk。
4诉植、檢測(cè)flume是否安裝成功祥国,切換到flume的bin目錄/usr/apache-flume-1.6.0-cdh5.7.0-bin/bin?
執(zhí)行flume-ng version命令查看flume的版本,如果出現(xiàn)下圖晾腔,則表示安裝成功
如何配置Agent舌稀?
# example.conf: A single-node Flume configuration
###自己的理解:使用Flume的關(guān)鍵就是寫(xiě)配置文件
A)配置Source
B)配置Channel
C)配置Sink
D)把以上三個(gè)組件串聯(lián)起來(lái)
a1:agent的名稱(chēng)
r1:source的名稱(chēng)
k1:sink的名稱(chēng)
c1:channel的名稱(chēng)
# Name the components on this agent
a1.sources=r1
a1.sinks=k1
a1.channels=c1
# Describe/configure the? source
a1.sources.r1.type=netcat? ? ##固定的類(lèi)型
a1.sources.r1.bind=localhost ##綁定的IP地址
a1.sources.r1.port=44444? ##需要監(jiān)聽(tīng)的服務(wù)端口,如果這個(gè)端口的服務(wù)有內(nèi)容輸出灼擂,就會(huì)被監(jiān)控到壁查,并把數(shù)據(jù)通過(guò)flume的事件發(fā)送過(guò)來(lái)。
解析如下:
# Describe the sink
a1.sinks.k1.type=logger? ##指定數(shù)據(jù)輸出形式
# 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
###把source-channel-sink建立聯(lián)系
a1.sources.r1.channels=c1? ##一個(gè)agent的source可以指定多個(gè)channel剔应,因此這里時(shí)channels
a1.sinks.k1.channel=c1 ##而一個(gè)agent的sink只能對(duì)應(yīng)一個(gè)channel睡腿。
把這個(gè)配置內(nèi)容保存在一個(gè)文件里面语御,存放在flume的根目錄conf文件夾下,我自己喜歡命名:
flume-setting.conf
啟動(dòng)flume
bin/flume-ng agent --conf $FLUME_HOME/conf --conf-file $FLUME_HOME/conf/flume-setting.conf --name a1 -Dflume.root.logger=INFO,console
測(cè)試是否能正常監(jiān)聽(tīng)端口
使用telnet ip 監(jiān)控的端口
上圖有Event內(nèi)容席怪,這里面有很多含義应闯,咱們拿一個(gè)樣例來(lái)說(shuō)下。
Event:{headers:{} body: 68 65 6C 6C 6F 0D? ? ? ?hello.}為例子挂捻。
Event:是Flume數(shù)據(jù)傳輸?shù)幕締卧?/p>
Event:是可選的headers+ byte array
至此碉纺,從指定的網(wǎng)絡(luò)端口采集日志數(shù)據(jù)輸出到控制臺(tái)已經(jīng)完成了。
第二個(gè)需求
要實(shí)現(xiàn)這個(gè)需求刻撒,我們就需要再重flume中做適合該需求的Agent的選項(xiàng)
在官網(wǎng)查找下來(lái)骨田,定下了這個(gè)選型:exec Source? +? memory Channel? +? logger Sink
我們把上面的需求的配置文件改動(dòng)下:
# Name the components on this agent
a1.sources=r1
a1.sinks=k1
a1.channels=c1
# Describe/configure the? source
a1.sources.r1.type=exec? ? ##shell命令類(lèi)型的
a1.sources.r1.command=tail -F /usr/test.log ##綁定監(jiān)控的日志文件
a1.sources.r1.shell=/bin/bash -c? ? ##固定填寫(xiě)
# Describe the sink
a1.sinks.k1.type=logger? ##指定數(shù)據(jù)輸出形式
# 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
###把source-channel-sink建立聯(lián)系
a1.sources.r1.channels=c1? ##一個(gè)agent的source可以指定多個(gè)channel,因此這里時(shí)channels
a1.sinks.k1.channel=c1 ##而一個(gè)agent的sink只能對(duì)應(yīng)一個(gè)channel声怔。
把這個(gè)配置內(nèi)容保存在一個(gè)文件里面态贤,存放在flume的根目錄conf文件夾下,我自己喜歡命名:
exec-memory-logger.conf
然后啟動(dòng)
bin/flume-ng agent --conf $FLUME_HOME/conf --conf-file?$FLUME_HOME/conf/exec-memory-logger.conf?--name a1 -Dflume.root.logger=INFO,console
這時(shí)候我們往/usr/test.log中添加點(diǎn)內(nèi)容醋火,看看是否能否被監(jiān)控到
echo 你好嗎 >> test.log
echo yes >> test.log
echo 我非常好 >> test.log
我們把監(jiān)控到的數(shù)據(jù)打印到控制臺(tái)抵卫,是沒(méi)有實(shí)際意義的,我們?nèi)绻氚驯O(jiān)控到的數(shù)據(jù)寫(xiě)入到我們的hdfs上去胎撇,改怎么處理?
繼續(xù)查找flume的官方開(kāi)發(fā)文檔:
既然是寫(xiě)入到hdfs殖氏,我們就必須去設(shè)置agent的sink配置晚树,來(lái)我們來(lái)找一下。
# Name the components on this agent
a1.sources=r1
a1.sinks=k1
a1.channels=c1
# Describe/configure the? source
a1.sources.r1.type=exec? ? ##shell命令類(lèi)型的
a1.sources.r1.command=tail -F /usr/test.log ##綁定監(jiān)控的日志文件
a1.sources.r1.shell=/bin/bash -c? ? ##固定填寫(xiě)
# Describe the sink
a1.sinks.k1.type=logger? ##指定數(shù)據(jù)輸出形式
# 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
###把source-channel-sink建立聯(lián)系
a1.sources.r1.channels=c1? ##一個(gè)agent的source可以指定多個(gè)channel雅采,因此這里時(shí)channels
a1.sinks.k1.channel=c1? ? ? ?##而一個(gè)agent的sink只能對(duì)應(yīng)一個(gè)channel爵憎。
a1.sinks.k1.hdfs.path = hdfs://flume/xcx/%y-%m-%d/%H%M/%S ###定義再hdfs的存儲(chǔ)目錄格式
a1.sinks.k1.hdfs.filePrefix = xcx-? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ###存儲(chǔ)文件前綴
a1.sinks.k1.hdfs.fileSuffix =.lzo????????????????????????????????????????????###存儲(chǔ)文件后綴
a1.sinks.k1.hdfs.codeC=lzo? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?###壓縮格式可選值gzip, bzip2, lzo, lzop, snappy
a1.sinks.k1.hdfs.writeFormat=Text? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ####存儲(chǔ)文件類(lèi)型Text?or?Writable
a1.sinks.k1.hdfs.round = true? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?###是否根據(jù)時(shí)間間隔滾動(dòng)產(chǎn)生文件
a1.sinks.k1.hdfs.roundValue = 10? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ###10
a1.sinks.k1.hdfs.roundUnit = minute? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?###單位? 可選值 second, minute or hour.
把這個(gè)配置內(nèi)容保存在一個(gè)文件里面,存放在flume的根目錄conf文件夾下婚瓜,我自己喜歡命名:
exec-memory-hdfs.conf
這里我有個(gè)疑問(wèn)宝鼓,flume是如何知道我的hdfs服務(wù)器位置的尼?拿到只用一個(gè) a1.sinks.k1.hdfs.path = hdfs://flume/xcx/%y-%m-%d/%H%M/%S ###定義再hdfs的存儲(chǔ)目錄格式就可以做到了嗎巴刻?如果flume不跟hdfs部署在同一臺(tái)服務(wù)器愚铡,這種方式還有效嗎?
咱們就引出來(lái)了第三個(gè)需求:
我們的技術(shù)選型:這里的avro sink就是用來(lái)跨機(jī)器的傳輸格式
第一組:exec source + memory channel + avro sink
第二組:avro source + memory channel + logger sink
有幾組就要編寫(xiě)幾個(gè)agent配置文件
第一組agent文件名:exec-memory-avro.conf
######begin######
# Name the components on this agent
exec-memory-avro.sources=exec-source
exec-memory-avro.sinks=avro-sink
exec-memory-avro.channels=memroy-channel
# Describe/configure the? source
exec-memory-avro.sources.exec-source.type=exec? ? ##shell命令類(lèi)型的
exec-memory-avro.sources.exec-source.command=tail -F /usr/test.log ##綁定監(jiān)控的日志文件
exec-memory-avro.sources.exec-source.shell=/bin/bash -c? ? ##固定填寫(xiě)
exec-memory-avro.sinks.avro-sink.type=avro ##指定數(shù)據(jù)輸出形式
exec-memory-avro.sinks.avro-sink.hostname=192.168.32.129 ####數(shù)據(jù)需要寫(xiě)入的目標(biāo)服務(wù)器ip
exec-memory-avro.sinks.avro-sink.port=44444? ?####所在端口
exec-memory-avro.channels.memroy-channel.type=memory
exec-memory-avro.channels.memroy-channel.capacity=1000
exec-memory-avro.channels.memroy-channel.transactionCapacity=100
###把source-channel-sink建立聯(lián)系
exec-memory-avro.sources.exec-source.channels=memroy-channel ##一個(gè)agent的source可以指定多個(gè)channel胡陪,因此這里時(shí)channels
exec-memory-avro.sinks.avro-sink.channel=memroy-channel ##而一個(gè)agent的sink只能對(duì)應(yīng)一個(gè)channel沥寥。
######end######
第二組agent文件名:avro-memory-logger.conf
######begin######
# Name the components on this agent
avro-memory-logger.sources=avro-source
avro-memory-logger.sinks=logger-sink
avro-memory-logger.channels=memroy-channel
# Describe/configure the? source
avro-memory-logger.sources.avro-source.type=avro?
avro-memory-logger.sources.avro-source.bind=192.168.32.72
avro-memory-logger.sources.avro-source.port=44444
avro-memory-logger.sinks.logger-sink.type=logger ##指定數(shù)據(jù)輸出形式
avro-memory-logger.channels.memroy-channel.type=memory
avro-memory-logger.channels.memroy-channel.capacity=1000
avro-memory-logger.channels.memroy-channel.transactionCapacity=100
###把source-channel-sink建立聯(lián)系
avro-memory-logger.sources.avro-source.channels=memroy-channel?##一個(gè)agent的source可以指定多個(gè)channel,因此這里時(shí)channels
avro-memory-logger.sinks.logger-sink.channel=memroy-channel?##而一個(gè)agent的sink只能對(duì)應(yīng)一個(gè)channel柠座。
######end######
啟動(dòng)Flume
這里要由于有兩個(gè)agent邑雅,所以要有個(gè)啟動(dòng)順序
需要先啟動(dòng):avro-memory-logger
bin/flume-ng agent --conf $FLUME_HOME/conf --conf-file?$FLUME_HOME/conf/avro-memory-logger.conf?--name avro-memory-logger -Dflume.root.logger=INFO,console
然后再啟動(dòng):exec-memory-avro
bin/flume-ng agent --conf $FLUME_HOME/conf --conf-file?$FLUME_HOME/conf/exec-memory-avro.conf?--name?exec-memory-avro?-Dflume.root.logger=INFO,console
關(guān)閉flume
ps -ef|grep flume,查出進(jìn)程號(hào)妈经,然后kill pid即可
注意:改動(dòng)flume的配置之后淮野,重啟flume捧书,重啟前未被發(fā)出來(lái)的消息還依然會(huì)重發(fā)。