一、Flume简介

1) Flume提供一个分布式的,可靠的,对大数据量的日志进行高效收集、聚集、移动的服务,Flume只能在Unix环境下运行。

2) Flume基于流式架构,容错性强,也很灵活简单。

参考: 大数据架构中的流式架构和Kappa架构

   流式架构/反应式编程(Reactive Architecture/Programming)

直接取消了批处理操作,数据全程以数据流的方式进行处理,所以在数据接入端没有了ETL操作,转而替换为数据通道。

实效性非常高。

对于数据的重播和历史统计无法很好的支撑。对于离线分析仅仅支撑窗口之内的分析。经过流处理加工后的数据,通过消息中间件以消息的形式直接推送给了消费者。虽然有一个存储部分,但是该存储更多的以窗口的形式进行存储,所以该存储并非发生在数据湖,而是在外围系统。

流式架构的适用场景就是预警,监控,对数据有有效期要求的情况。这些就是流式架构的主要内容。

ETL(数据仓库技术) 

  •     ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL一词较常用在数据仓库,但其对象并不限于数据仓库
  • 业务系统的数据经过抽取、清洗转换之后加载到数据仓库的过程,目的是将企业中的分散、零乱、标准不统一的数据整合到一起,为企业的决策提供分析依据。

3) Flume、Kafka用来实时进行数据收集,Spark、Flink用来实时处理数据,impala用来实时查询

功能:

  •     支持在日志系统中定制各类数据发送方,用于收集数据;
  •     同时可提供对数据进行简单处理,并具有写到各种数据接收方(HDFS、Hbase等)的能力。

二、Flume作用

参考:    为什么需要flume以及flume的原理

    传输文件到hadoop,从日志收集服务器

flume的设计宗旨是向hadoop集群批量导入基于事件的海量数据。    

    一个典型的例子就是利用flume从一组web服务器中收集日志文件,然后把这些文件中的日志事件转移到一个新的HDFS汇总文件中以做进一步的处理,所以flume的终点sink一般是HDFS,当然因为flume本生的灵活性,又可以将采集到的数据输出到HDFS、hbase、hive、kafka等众多外部存储系统中

 

三、Flume结构

结构:Agent主要由:source,channel,sink三个组件组成。

flume采集上传hdfs flume采集数据到hdfs_flume采集上传hdfs

 

2.1、Source

1. 简介

用于采集数据,Source是产生数据流的地方,同时Source会将产生的数据流传输到Channel,这个有点类似于Java IO部分的Channel。

接收数据,并将接的数据以flume的event格式传递给一个或多个通道channel,flume提供多种数据接收方式,比如Avro,Thrift,twitter1%等;

    如果我们这里的Sources是另一个flume的sink,那么source的端口需要设置的和【另一个flume的sink的端口】相同。才能接收到数据。

2. 数据类型:

1) netcat    一个端口的数据流  : $ telnet bigdata111 44445   登录远程主机,输入数据

 一个NetCat Source用来监听一个指定端口,并将接收到的数据的每一行转换为一个事件。

属性

  • type : 组件类型名称
  • bind :要监听的主机名或IP地址
  • port :要绑定的端口号

2)exec

   Exec Source在启动时运行给定的Unix命令,然后通过这个命令不断输出数据,将命令产生的输出作为源。如果进程由于任何原因退出,source也会退出,并且不会生成更多数据。

  • type:exec
  • command是unix命令
  •  spooldir    

新增的文件,并将文件中的数据读取出来。其中,Spool Source有2个注意地方,第一个是拷贝到spool目录下的文件不可以再打开编辑,第二个是spool目录下不可包含相应的子目录。这个主要用途作为对日志的准实时监控

  • Avro 序列化  【Apache Avro是数据序列化的系统】

  监听AVRO端口,来接受来自外部AVRO客户端的事件流。avro-source接收到的是经过avro序列化后的数据,然后 反序列化数据继续传输。所以,如果是avro-source的话,源数据必须是经过avro序列化后的数据。接收通过flume提供的avro客户端发送的日 志信息。

2.2、Channel

用于桥接Sources和Sinks,类似于一个队列。【可以理解为一个缓存】

短暂的存储容器,它将从source处接收到event格式的数据缓存起来,直到它们被sinks消费掉,它在source和sink间起着桥梁的作用,channel是一个完整的事物,这一点保住了数据在收发的时候的一致性。并且它可以和任意数量的source和sink链接。支持类型有:JDBC channel,File System channel, Memort channel等。

2.3、Sink

1. 简介

从Channel收集数据,将数据写到目标源(可以是下一个Source,也可以是HDFS或者HBase)。

   将数据存储到集中存储器比如Hbase和HDFS,它从channels消费数据(event)并将其传递给目标地。目标地可能是另一个sink,也可能是HDFS、Hbase.

2. 数据类型

1.  avro        序列化

   avro sink形成了Flume分层收集支持的一半。 发送到此接收器的Flume事件将转换为Avro事件并发送到配置的主机名/端口对。 事件从已配置的通道以批量配置的批处理大小获取

2.  hdfs       

将事件写入Hadoop分布式文件系统(HDFS)。 它目前支持创建文本和序列文件。 它支持两种文件类型的压缩。

  • 可以基于经过的时间或数据大小或事件数量来周期性地滚动文件(关闭当前文件并创建新文件)。
  • 它还通过属性(例如事件发生的时间戳或机器)来对数据进行桶/分区。
  • HDFS目录路径可能包含将由HDFS接收器替换的格式化转义序列,以生成用于存储事件的目录/文件名。

属性:参考--flume采集中HDFS参数解析 

  • type  :hdfs
  • path    :写入hdfs的路径,需要包含文件系统标识,比如:hdfs://bigdata111:9000/flume/%H
  • filePrefix   :写入hdfs的文件名的前缀,可以使用flume提供的日期及%{host}表达式。
  • fileSuffix  :写入hdfs的文件名后缀,比如:.lzo .log等。
  • rollInterval  :hdfs sink间隔多长将临时文件滚动成最终目标文件,单位:秒;如果设置成0,则表示不根据时间来滚动文件;注:滚动(roll)指的是,hdfs sink将临时文件重命名成最终目标文件,并新打开一个临时文件来写入数据;滚动文件即指将HDFS上生成的以.tmp结尾的临时文件转换为实际存储文件。默认值:30。
  • rollSize  :当临时文件达到该大小(单位:bytes)时,滚动成目标文件;如果设置成0,则表示不根据临时文件大小来滚动文件;默认值:1024
  • rollCount  :当events数据达到该数量时候,将临时文件滚动成目标文件;如果设置成0,则表示不根据events数量来滚动文件;默认值:10
  • batchSize  :每个批次刷新到HDFS上的events数量;默认值:100
  • fileType  :文件格式,包括:SequenceFile, DataStream,CompressedStream。默认值:SequenceFile。当使用DataStream时候,文件不会被压缩
  • useLocalTimeStamp  :是否使用当地时间
  • round :默认值:false,是否启用时间上的”舍弃”,类似于”四舍五入”,如果启用,则会影响除了%t的其他所有时间表达式;
  • roundValue  :默认值:1,时间上进行“舍弃”的值;
  • roundUnit  :默认值:seconds,时间上进行”舍弃”的单位,包含:second,minute,hour

参考:解决Flume采集数据时在HDFS上产生大量小文件的问题

   当设置了round、roundValue、roundUnit参数收,需要在sink指定的HDFS路径上指定按照时间生成的目录的格式,例如有需求,每采集1小时就在HDFS目录上生成一个目录,里面存放这1小时内采集到的数据。

编写sink部分的配置文件如下:

a1.sinks.k1.hdfs.path = hdfs://nameservice1/tmp/flume/jbw/%y-%m-%d/%H%M%S
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.roundValue = 60
a1.sinks.k1.hdfs.roundUnit = minute当时间为2018-6-7 10:00:00时候,hdfs.path会被解析为:
hdfs://nameservice1/tmp/flume/jbw/20180607/10:00:00
在时间为2018-6-7 10:59:59时候,hdfs.path依旧会被解析为:
hdfs://nameservice1/tmp/flume/jbw/20180607/10:00:00
在时间为2018-6-7 11:02:00时候,hdfs.path则会被解析为:
hdfs://nameservice1/tmp/flume/jbw/20180607/11:00:00

 

3.  file_roll   

在本地文件系统中存储事件。

4) logger   日志文件

记录指定级别(比如INFO,DEBUG,ERROR等)的日志

属性

  • type : logger

2.4、Event

传输单元,Flume数据传输的基本单元,以事件的形式将数据从源头送至目的地

日志数据(字节数据组形式)并且携带有头信息,这些event由Agent外部的Source生成。

三、Flume传输过程

     1.  source监控某个文件或数据流,数据源产生新的数据

     2.  拿到该数据后,将数据封装在一个Event中

     3.  并put到channel后commit提交,channel队列先进先出

     4.  sink去channel队列中拉取数据,然后写入到HDFS中。

四、Flume文件配置【只在bigdata112上配置了】

查询JAVA_HOME:       echo $JAVA_HOME

显示/opt/module/jdk1.8.0_144  /opt/module/jdk1.8.0_144

安装Flume

[itstar@bigdata112 software]$ tar -zxvf apache-flume1.8.0-bin.tar.gz -C /opt/module/

改名:【/opt/module/flume-1.8.0/conf

[itstar@bigdata112 conf]$ mv flume-env.sh.template flume-env.sh

flume-env.sh中改变

export JAVA_HOME=/opt/module/jdk1.8.0_144

五。案例一:监控端口数据

1. 目标:

Flume监控一端Console,另一端Console发送消息,使被监控端实时显示。

2. 过程:

flume采集上传hdfs flume采集数据到hdfs_大数据_02

  •       Flume从44445端口传入
  •       在控制台打印“pingguo“之后,Source接收数据,接收端口一定要用netcat类型
  •       通过数据流传输到Channel里面,走的是memory(内存),比较快。
  •        Memory通过缓存走到Sink,类型走的是logger日志。

3. 分步实现:

1) 安装telnet工具

【联网状态】yum -y install telnet

  •       -y(当安装过程提示选择全部为"yes")

Linux telnet命令用于远端登入。

执行telnet指令开启终端机阶段作业,并登入远端主机。

2) 创建Flume Agent配置文件flume-telnet.conf

在 /opt/module/flume-1.8.0/jobconf 中建立文件flume-telnet.conf。将以下文件放入flume-telnet.conf中。

#1.定义Agent ===> a1
a1.sources = r1
a1.sinks = k1
a1.channels = c1
 
#2.定义source
a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata112
a1.sources.r1.port = 44445
 
#3.定义sink
a1.sinks.k1.type = logger
 
#4.定义channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
 
#5.双向链接
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

 

3) 判断44445端口是否被占用

$ netstat -tunlp | grep 44445

4) 启动flume配置文件

注意:末尾的“ \”表示下一行的连接下一行的内容    

/opt/module/flume1.8.0/bin/flume-ng agent \
--conf /opt/module/flume1.8.0/conf/ \
--name a1 \
--conf-file /opt/module/flume1.8.0/jobconf/flume-telnet.conf \   #配置文件所在的地方
-Dflume.root.logger==INFO,console

      

flume采集上传hdfs flume采集数据到hdfs_flume采集上传hdfs_03

  -Dflume.root.logger==INFO,console   #打印控制台目录的

5) 使用telnet工具登录本机

$ telnet bigdata111 44445

6) 使用telnet工具向本机的4445端口发送内容

发送:  

flume采集上传hdfs flume采集数据到hdfs_hdfs_04

接收:  

flume采集上传hdfs flume采集数据到hdfs_hdfs_05

六。案例二:实时读取本地文件到HDFS【文件案例监控】

1) 创建flume-hdfs.conf文件

         在 /opt/module/flume-1.8.0/jobconf 中建立文件。

# 1.定义agent的名字a2
a2.sources = r2
a2.sinks = k2
a2.channels = c2

#2.定义Source
a2.sources.r2.type = exec
a2.sources.r2.command = tail -F /opt/Andy
a2.sources.r2.shell = /bin/bash -c

#3.定义sink
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs://bigdata111:9000/flume/%H

#写入hdfs的文件名的前缀
a2.sinks.k2.hdfs.filePrefix = Andy-
#是否按照时间滚动文件夹
a2.sinks.k2.hdfs.round = true
#多少时间单位创建一个新的文件夹
a2.sinks.k2.hdfs.roundValue = 1
#重新定义时间单位
a2.sinks.k2.hdfs.roundUnit = hour
#是否在hfds上目录使用本地时间戳
a2.sinks.k2.hdfs.useLocalTimeStamp = true
#积攒多少个Event才flush到HDFS一次
a2.sinks.k2.hdfs.batchSize = 1000
#设置文件类型,当使用DataStream时候,文件不会被压缩。使用文本文件,不使用sequenceFile
a2.sinks.k2.hdfs.fileType = DataStream
#多长时间写数据到新文件;600秒。hdfs间隔多长将临时文件滚动成最终目标文件,单位:秒;滚动(roll)指的是,hdfs sink将临时文件重命名成最终目标文件,并新打开一个临时文件来写入数据
a2.sinks.k2.hdfs.rollInterval = 600
#设置每个文件的滚动大小。文件达到多少数据量时,写新文件。当临时文件达到该大小(单位:bytes)时,滚动成目标文件。
a2.sinks.k2.hdfs.rollSize = 134217700
#当events数据达到该数量时候,将临时文件滚动成目标文件;如果设置成0,则表示不根据events数量来滚动文件;默认值:10
a2.sinks.k2.hdfs.rollCount = 0
#最小副本数
a2.sinks.k2.hdfs.minBlockReplicas = 1

# 4.定义Channel
a2.channels.c2.type = memory
a2.channels.c2.capacity = 1000
a2.channels.c2.transactionCapacity = 100

# 5.链接
a2.sources.r2.channels = c2
a2.sinks.k2.channel = c2

补充:

     Linux【八】【转】bash -c 注意事项

注意:

  • a2.sources.r2.type = exec#低于1.6的版本都是这个,表示文件类型
  • a2.sources.r2.command = tail -F /opt/Andy#tail -F 监控 文件名
  • a2.sources.r2.shell = /bin/bash -c#写死的,不用更改
  • a2.sinks.k2.hdfs.path = hdfs://bigdata111:9000/flume/%H#%H 当前的小时数
  • a2.sinks.k2.hdfs.rollSize = 134217700 #128MB。当临时文件达到该大小(单位:bytes)时,滚动成目标文件。

这里指的是每隔一小时会产生一个新的文件夹。比如现在是/flume/05,一小时后会产生/flume/06

  • a2.sinks.k2.hdfs.roundValue = 1
  • a2.sinks.k2.hdfs.roundUnit = hour

3) 执行监控配置

/opt/module/flume-1.8.0/bin/flume-ng agent \
--conf /opt/module/flume1.8.0/conf/ \
--name a2 \
--conf-file /opt/module/flume-1.8.0/jobconf/flume-hdfs.conf

      

flume采集上传hdfs flume采集数据到hdfs_flume采集上传hdfs_06

 4) 执行完命令之后,HDFS中没有出现这个文件

 5)改变文件之后,查看结果 

  当改变文件/opt/Andy之后,在http://bigdata111:50070/页面中从出现了文件 【/flume/05/Andy-.1570624975346.tmp】

  这个时候没有满一小时,文件名中含有tmp。等过了1小时之后,这个tmp会被去掉。【但是事实好像不是这样】

flume采集上传hdfs flume采集数据到hdfs_数据_07

 

flume采集上传hdfs flume采集数据到hdfs_大数据_08

 6)在过了一段时间之后,大概10分钟。变成了

flume采集上传hdfs flume采集数据到hdfs_HDFS_09

7)测试关于hdfs的一些属性(roll)

  rollInterval  表示 hdfs sink间隔多长将临时文件滚动成最终目标文件,并新打开一个临时文件来写入数据;滚动文件即指将HDFS上生成的以.tmp结尾的临时文件转换为实际存储文件。默认值:30。

  当我们运行命令的时候,生成一个tmp文件,这里保存的是监控的文件的原有内容。由于我们设置的rollInterval是300秒,查看测试结果的变化,经过300秒,tmp文件临时文件转化为了最终文件。然后生成了新的tmp文件。新的文件中只有新添加的数据,没有原有的数据。

(1)Andy文件

flume采集上传hdfs flume采集数据到hdfs_HDFS_10

(2)改动

将flume-hdfs.conf的这两个属性的值进行改动

a2.sinks.k2.hdfs.rollInterval = 300
a2.sinks.k2.hdfs.roundUnit = minute

(3)运行文件

生成了文件Andy-.1573130714695.tmp,查看文件Andy-.1573130714695.tmp

flume采集上传hdfs flume采集数据到hdfs_hdfs_11

flume采集上传hdfs flume采集数据到hdfs_hdfs_12

(4)经过1分钟查看变化

经过了1分钟,没有变化。

(5)5分钟(300秒)后临时文件滚动成了最终文件。

(6)追加内容,产生了新的tmp文件

(7)再次追加内容,没有产生新文件。(这次的追加“2”和追加“1”的操作只隔了5秒)

flume采集上传hdfs flume采集数据到hdfs_HDFS_13

flume采集上传hdfs flume采集数据到hdfs_HDFS_14

(8)查看Andy-.1573131205163.tmp文件,只有我们添加的内容。而Andy-.1573130714695文件中只有原来的内容。

flume采集上传hdfs flume采集数据到hdfs_flume采集上传hdfs_15

flume采集上传hdfs flume采集数据到hdfs_数据_16

8)测试关于hdfs的一些属性(round)

当设置了round、roundValue、roundUnit参数,需要在sink指定的HDFS路径上指定按照时间生成的目录的格式,当有需求(我理解的是文件变动)。每隔roundValue的时间【这个例子是1分钟】,就在HDFS目录上生成一个目录,里面存放这1分钟内采集到的数据。

   最开始生成的hdfs文件存储的是要监控文件的全部内容。之后在追加以后生成的hdfs文件,只保存了追加的数据。

(1)Andy文件

flume采集上传hdfs flume采集数据到hdfs_HDFS_10

(2)改动

将flume-hdfs.conf的这两个属性的值进行改动

a2.sinks.k2.hdfs.path = hdfs://bigdata111:9000/flume/%M
#a2.sinks.k2.hdfs.rollInterval = 300
#a2.sinks.k2.hdfs.rollSize = 134217700
#a2.sinks.k2.hdfs.rollCount = 0

a2.sinks.k2.hdfs.roundUnit = minute
a2.sinks.k2.hdfs.roundValue = 1

(3)运行文件

不做任何改动的情况下,经过35秒,生成一个最终文件。继续观察,又经过了两分钟,没有任何变化,没有产生新文件。

flume采集上传hdfs flume采集数据到hdfs_数据_18

flume采集上传hdfs flume采集数据到hdfs_数据_19

(4)追加内容

我们设置的hdfs路径是【/flume/分钟数】。产生新的tmp文件 Andy-.1573132979481.tmp,它的文件夹是22。相隔6秒,再次追加,然后产生了新文件Andy-.1573132984425.tmp,它的文件是23。看起来是如果是在不同的分钟数下,每添加一次就会产生一个新文件。这两个临时文件经过30秒【因为roolInterval默认值:30。】,变成了最终文件。

flume采集上传hdfs flume采集数据到hdfs_flume采集上传hdfs_20

flume采集上传hdfs flume采集数据到hdfs_大数据_21

flume采集上传hdfs flume采集数据到hdfs_HDFS_22

flume采集上传hdfs flume采集数据到hdfs_大数据_23

(5)继续追加内容

我们在23分钟这个时间内进行了两次文件添加,但是只产生了一个文件Andy-.1573133411209.tmp。

flume采集上传hdfs flume采集数据到hdfs_hdfs_24

flume采集上传hdfs flume采集数据到hdfs_数据_25

flume采集上传hdfs flume采集数据到hdfs_HDFS_26

七。案例三:实时读取目录文件到HDFS

目标:使用flume监听整个目录的文件

分步实现

1) 创建配置文件flume-dir.conf

#1.定义Agent a3
a3.sources = r3
a3.sinks = k3
a3.channels = c3
 
# 2.定义Source
a3.sources.r3.type = spooldir
a3.sources.r3.spoolDir = /opt/module/flume-1.8.0/upload
a3.sources.r3.fileSuffix = .COMPLETED # 文件读取后添加的后缀名
a3.sources.r3.fileHeader = true
#忽略所有以.tmp结尾的文件,不上传
a3.sources.r3.ignorePattern = ([^ ]*\.tmp)
 
# 3.Sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://bigdata111:9000/flume/%H
#写入hdfs的文件名的前缀
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
#设置文件类型,当使用DataStream时候,文件不会被压缩
a3.sinks.k3.hdfs.fileType = DataStream
#hdfs间隔多长将临时文件滚动成最终目标文件,单位:秒;滚动(roll)指的是,hdfs sink将临时文件重命名成最终目标文件,并新打开一个临时文件来写入数据
a3.sinks.k3.hdfs.rollInterval = 600
#设置每个文件的滚动大小大概是128M。当临时文件达到该大小(单位:bytes)时,滚动成目标文件
a3.sinks.k3.hdfs.rollSize = 134217728
#文件的滚动与Event数量无关。当events数据达到该数量时候,将临时文件滚动成目标文件;如果设置成0,则表示不根据events数量来滚动文件;默认值:10
a3.sinks.k3.hdfs.rollCount = 0
#最小副本数
a3.sinks.k3.hdfs.minBlockReplicas = 1
 
#4.定义Channel
a3.channels.c3.type = memory
a3.channels.c3.capacity = 1000
a3.channels.c3.transactionCapacity = 100
 
#5.链接
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3

2) 执行测试:执行如下脚本后,请向upload文件夹中添加文件试试

/opt/module/flume-1.8.0/bin/flume-ng agent \
--conf /opt/module/flume-1.8.0/conf/ \
--name a3 \
--conf-file /opt/module/flume-1.8.0/jobconf/flume-dir.conf

     或者

[root@bigdata112 flume-1.8.0]# bin/flume-ng agent --conf conf/ --name a3 --conf-file jobconf/flume-dir.conf

3) 执行命令后在upload文件夹中创建A 和 B文件夹。

flume采集上传hdfs flume采集数据到hdfs_大数据_27

flume采集上传hdfs flume采集数据到hdfs_数据_28

flume采集上传hdfs flume采集数据到hdfs_flume采集上传hdfs_29

4)查看结果

flume采集上传hdfs flume采集数据到hdfs_hdfs_30

flume采集上传hdfs flume采集数据到hdfs_数据_31

5) 过了一段时间变成了这样(不超过10分钟)

flume采集上传hdfs flume采集数据到hdfs_大数据_32

 

尖叫提示:

1) 不要在监控目录中创建并持续修改文件

2) 上传完成的文件会以.COMPLETED结尾

3) 被监控文件夹每500毫秒扫描一次文件变动