flume

转自http://dblab.xmu.edu.cn

这里主要记录配置文件。

案例一:flume推送消息给Spark Streaming,Spark Streaming收到消息后进行处理。

把Flume Source设置为netcat类型,从终端上不断给Flume Source发送各种消息,Flume把消息汇集到Sink,这里把Sink类型设置为avro,由Sink把消息推送给Spark Streaming,由我们编写的Spark Streaming应用程序对消息进行处理。

cd /usr/local/flume
cd conf
vim flume-to-spark.conf

在flume-to-spark.conf文件中写入如下内容: 

        # 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 = 33333

        # Describe the sink
        a1.sinks.k1.type = avro
        a1.sinks.k1.hostname = localhost
        a1.sinks.k1.port =44444

        # Use a channel which buffers events in memory
        a1.channels.c1.type = memory
        a1.channels.c1.capacity = 1000000
        a1.channels.c1.transactionCapacity = 1000000

        # Bind the source and sink to the channel
        a1.sources.r1.channels = c1
        a1.sinks.k1.channel = c1

在上面的配置文件中,我们把Flume Source类别设置为netcat,绑定到localhost的33333端口,这样,我们后面就可以通过“telnet localhost 33333”命令向Flume Source发送消息。

同时,我们把Flume Sink类别设置为avro,绑定到localhost的44444端口,这样,Flume Source把采集到的消息汇集到Flume Sink以后,Sink会把消息推送给localhost的44444端口,而我们编写的Spark Streaming程序一直在监听localhost的44444端口,一旦有消息到达,就会被Spark Streaming应用程序取走进行处理。

特别要强调的是,上述配置文件完成以后,暂时“不要”启动Flume Agent,如果这个时候使用“flume-ng agent”命令启动agent,就会出现错误提示“localhost:44444拒绝连接”,也就是Flume Sink要发送消息给localhost的44444端口,但是,无法连接上localhost的44444端口。为什么会出现这个错误呢?因为,这个时候我们还没有启动Spark Streaming应用程序,也就没有启动localhost的44444端口,所以,Sink是无法向这个端口发送消息的。

spark的准备工作

Kafka和Flume等高级输入源,需要依赖独立的库(jar文件)。

现在我们就需要下载spark-streaming-flume_2.11-2.1.0.jar,其中2.11表示对应的Scala版本号,2.1.0表示Spark版本号。

cd /usr/local/spark/jars
mkdir flume
cd ~
cd 下载
cp ./spark-streaming-flume_2.11-2.1.0.jar /usr/local/spark/jars/flume

下面我们还要修改spark目录下conf/spark-env.sh文件中的SPARK_DIST_CLASSPATH变量.把flume的相关jar包添加到此文件中

export SPARK_DIST_CLASSPATH=$(/usr/local/hadoop/bin/hadoop classpath):$(/usr/local/hbase/bin/hbase classpath):/usr/local/spark/examples/jars/*:/usr/local/spark/jars/kafka/*:/usr/local/kafka/libs/*:/usr/local/spark/jars/flume/*:/usr/local/flume/lib/*

这样,我们就已经准备好了Spark环境,它可以支持Flume相关编程了。

编写Spark程序使用Flume数据源

cd /usr/local/spark/mycode
mkdir flume
cd flume
vim FlumeEventCount.py

请在FlumeEventCount.py代码文件中输入以下代码:

from __future__ import print_function
 
import sys
 
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
from pyspark.streaming.flume import FlumeUtils
import pyspark
if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: flume_wordcount.py <hostname> <port>", file=sys.stderr)
        exit(-1)
 
    sc = SparkContext(appName="FlumeEventCount")
    ssc = StreamingContext(sc, 2)
 
    hostname= sys.argv[1]
    port = int(sys.argv[2])
    stream = FlumeUtils.createStream(ssc, hostname, port,pyspark.StorageLevel.MEMORY_AND_DISK_SER_2)
    stream.count().map(lambda cnt : "Recieve " + str(cnt) +" Flume events!!!!").pprint()
 
    ssc.start()
    ssc.awaitTermination()  

测试程序效果

首先,请新建第1个Linux终端,启动Spark Streaming应用程序,命令如下:

cd /usr/local/spark
./bin/spark-submit --driver-class-path /usr/local/spark/jars/*:/usr/local/spark/jars/flume/* ./mycode/flume/FlumeEventCount.py localhost 44444

通过上面命令,我们为应用程序提供host和port两个参数的值分别为localhost和44444,程序会对localhost的44444端口进行监听,Milliseconds(2000)设置了时间间隔为2秒,所以,该程序每隔2秒就会从指定的端口中获取由Flume Sink发给该端口的消息,然后进行处理,对消息进行统计,打印出“Received 0 flume events.”这样的信息。  

现在,我们可以再另外新建第2个终端,在这个新的终端中启动Flume Agent,命令如下:

cd /usr/local/flume
bin/flume-ng agent --conf ./conf --conf-file ./conf/flume-to-spark.conf --name a1 -Dflume.root.logger=INFO,console  

注意以上几个参数:

--conf:    配置文件目录

--conf-file: 配置文件位置

--name:  agent的名字

启动agent以后,该agent就会一直监听localhost的33333端口,这样,我们下面就可以通过“telnet localhost 33333”命令向Flume Source发送消息。

请另外新建第3个终端,执行如下命令:

telnet localhost 33333

执行该命令以后,就可以在这个窗口里面随便敲入若干个字符和若干个回车,这些消息都会被Flume监听到,Flume把消息采集到以后汇集到Sink,然后由Sink发送给Spark的FlumeEventCount程序进行处理。然后,你就可以在运行FlumeEventCount的前面那个终端窗口内看到类似如下的统计结果:

-------------------------------------------
Time: 1488029430000 ms
-------------------------------------------
Received 0 flume events.
#这里省略了其他屏幕信息
-------------------------------------------
Time: 1488029432000 ms
-------------------------------------------
Received 8 flume events.
#这里省略了其他屏幕信息
-------------------------------------------
Time: 1488029434000 ms
-------------------------------------------
Received 21 flume events.

  

案例二:Avro source  

Avro可以发送一个给定的文件给Flume,Avro 源使用AVRO RPC机制。

a) 创建agent配置文件

  cd /usr/local/flume
  sudo vim ./conf/avro.conf #在conf目录下编辑一个avro.conf空文件

然后,我们在avro.conf写入以下内容  

  a1.sources = r1
  a1.sinks = k1
  a1.channels = c1
 
# Describe/configure the source
  a1.sources.r1.type = avro
  a1.sources.r1.channels = c1
  a1.sources.r1.bind = 0.0.0.0
  a1.sources.r1.port = 4141
    #注意这个端口名,在后面的教程中会用得到
 
# 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  

参数说明:

a1.sources.r1.type = avro,表示数据源的类型是avro。

bind绑定的ip地址或主机名,使用0.0.0.0表示绑定机器所有的接口。  

port表示绑定的端口。  

a1.sinks.k1.type = logger,表示sinks的类型是logger。

b) 启动flume agent a1

  /usr/local/flume/bin/flume-ng agent -c . -f /usr/local/flume/conf/avro.conf -n a1 -Dflume.root.logger=INFO,console #启动日志控制台  

参数说明:

-c同--conf.

-f同--conf-file.

-n同--name

agent启动成功会显示类似:INFO source.AvroSource: Avro source r1 started.

c) 创建指定文件

先打开另外一个终端,在/usr/local/flume下写入一个文件log.00,内容为hello,world:

  cd /usr/local/flume
  sudo sh -c 'echo "hello world" > /usr/local/flume/log.00'

我们再打开另外一个终端,执行:  

  cd /usr/local/flume
  bin/flume-ng avro-client --conf conf -H localhost -p 4141 -F /usr/local/flume/log.00 #4141是avro.conf文件里的端口名

此时我们可以看到第一个终端(agent窗口)下的显示,也就是在日志控制台,就会把log.00文件的内容打印出来.

案例三:netcatsource

a) 创建agent配置文件

  cd /usr/local/flume
  sudo vim ./conf/example.conf #在conf目录创建example.conf

在example.conf里写入以下内容:  

    # 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

b)启动flume agent (即打开日志控制台):  

  /usr/local/flume/bin/flume-ng agent --conf ./conf --conf-file ./conf/example.conf --name a1 -Dflume.root.logger=INFO,console

再打开一个终端,输入命令:telnet localhost 44444  

然后我们可以在终端下输入任何字符,第一个终端的日志控制台也会有相应的显示,如我们输入”hello,world”,得出

这里补充一点,flume只能传递英文和字符,不能用中文。

案例四:模拟两个agent之间传递消息的场景

 

说明:

1.在hadoop1机器上有一个flume agent,通过exec监听tail命令输出的结果。 
2.新增的结果通过avro sink的方式下沉到hadoop2:4141的avro source端。 
3.在hadoop2机器上有一个flume agent,通过avro source来接收下沉过来的数据。

编写hadoop1上的通信配置文件

在hadoop1上的flume通信控制的文件agent1.conf的内容如下: 

agent1.channels.ch1.type = memory
agent1.channels.ch1.capacity = 1000
agent1.channels.ch1.transactionCapacity = 100

agent1.sources.exec-source1.channels = ch1
agent1.sources.exec-source1.type = exec
agent1.sources.exec-source1.command = tail -F /opt/classiclaw/nginx/logs/access.log

agent1.sinks.avro-sink1.channel = ch1
agent1.sinks.avro-sink1.type = avro
agent1.sinks.avro-sink1.hostname = ubuntu
agent1.sinks.avro-sink1.port = 44444

agent1.channels = ch1
agent1.sources = exec-source1
agent1.sinks = avro-sink1

编写hadoop2上的通信配置文件

在hadoop2上的flume通信控制的文件agent2.conf的内容如下:  

agent2.channels.ch2.type = memory
agent2.channels.ch2.capacity = 1000
agent2.channels.ch2.transactionCapacity = 100

agent2.sources.avro-source1.channels = ch2
agent2.sources.avro-source1.type = avro
agent2.sources.avro-source1.bind = 0.0.0.0
agent2.sources.avro-source1.port = 44444

agent2.sinks.log-sink1.channel = ch2
agent2.sinks.log-sink1.type = logger

agent2.channels = ch2
agent2.sources = avro-source1
agent2.sinks = log-sink1

执行命令,开始测试

启动hadoop2上的flume agent

由于hadoop1上的agent配置文件中配置下沉的位置是hadoop2:4141,所以需要先启动hadoop2上的flume agent 
启动命令是:  

cd /usr/local/flume
./bin/flume-ng agent -c conf -f conf/agent2.conf -n agent2 -Dflume.root.logger=INFO,console  

启动效果图如下:

启动hadoop1上的flume agent

cd /usr/local/flume    
./bin/flume-ng agent -c conf -f conf/agent1.conf -n agent1 -Dflume.root.logger=INFO,console  

启动信息:

查看hadoop2上的运行效果

 

 通过上图发现只要access.log中有日志文件变化,在hadoop2上的agent就会有响应结果。

案例五: flume搜集日志:如何解决实时不断追加的日志文件及不断增加的文件个数问题 

背景:

在搜集日志的过程中,日志文件的个数及日志文件需要不断的追加。flume1.6中,可以使用tail -f可以解决不断追加的文件,但是由于日志文件的个数是变化的,不可能只产生一个文件。所以tail -f就已经不能解决这个搜集日志的问题。

需求:

需要能够监控文件,并且追加文件,同时文件个数也是不断变化的。

解决办法:

这时候flume1.7就产生了,很好的通过 TAILDIR解决了这个问题。TAILDIR可以监控一个目录下的文件。

1. 单节点的agent

1) 增加配置文件

cd $FLUME_HOME/conf
vim single_agent.conf

编写single_agent.conf

# agent的名称为a1
a1.sources = source1
a1.channels = channel1
a1.sinks = sink1

# set source
a1.sources.source1.type = TAILDIR
a1.sources.source1.positionFile = /opt/classiclaw/nginx/logs/taildir_position.json
a1.sources.source1.filegroups = f1
a1.sources.source1.filegroups.f1 = /opt/classiclaw/nginx/logs/access.log.*
a1.sources.source1.headers.f1.headerKey1 = value1
a1.sources.source1.fileHeader = true

# set sink
a1.sinks.sink1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.sink1.brokerList = k8s01:9092
a1.sinks.sink1.topic = abouttaildir
a1.sinks.sink1.kafka.flumeBatchSize = 20
a1.sinks.sink1.kafka.producer.acks = 1
a1.sinks.sink1.kafka.producer.linger.ms = 1
a1.sinks.sink1.kafka.producer.compression.type = snappy

# set channel
a1.channels.channel1.type = file
a1.channels.channel1.checkpointDir = /opt/classiclaw/nginx/logs/flume_data/checkpoint
a1.channels.channel1.dataDirs = /opt/classiclaw/nginx/logs/flume_data/data

# bind
a1.sources.source1.channels = channel1
a1.sinks.sink1.channel = channel1

2. 查看kafka现有的topic  

cd /usr/local/kafka
./bin/kafka-topics.sh --zookeeper k8s01:2181 --list

3. 在kafka上创建名为abouttaildir的topic  

cd /usr/local/kafka
./bin/kafka-topics.sh --zookeeper k8s01:2181 --create --topic abouttaildir --replication-factor 1 --partitions 3

4. 启动flume  

cd /usr/local/flume
./bin/flume-ng agent --conf conf/ --conf-file conf/single_agent.conf --name a1 -Dflume.root.logger=INFO,console

 

5. 创建一个kafka的consumer  

当然,前提是已开启zookeeper和kafka.

cd /usr/local/kafka
./bin/kafka-console-consumer.sh --zookeeper k8s01:2181 --topic abouttaildir --from-beginning

6.  添加文件到flume source目录  

cd /opt/classiclaw/nginx/logs
echo -e "this is a test file! \nhttp://www.aboutyun.com20170820">access.log.1

7.  再次查看kafka consumer  

切换到创建kafka consumer的shell界面,会看到我们access.log.1\access.log.2中文件的内容被打印在屏幕上。 

 

agent:

 

posted @ 2018-08-21 15:54  始怡  阅读(788)  评论(0编辑  收藏  举报