一、Flume简介
1) Flume提供一个分布式的,可靠的,对大数据量的日志进行高效收集、聚集、移动的服务,Flume只能在Unix环境下运行。
2) Flume基于流式架构,容错性强,也很灵活简单。
参考: 大数据架构中的流式架构和Kappa架构
流式架构/反应式编程(Reactive Architecture/Programming)
直接取消了批处理操作,数据全程以数据流的方式进行处理,所以在数据接入端没有了ETL操作,转而替换为数据通道。
实效性非常高。
对于数据的重播和历史统计无法很好的支撑。对于离线分析仅仅支撑窗口之内的分析。经过流处理加工后的数据,通过消息中间件以消息的形式直接推送给了消费者。虽然有一个存储部分,但是该存储更多的以窗口的形式进行存储,所以该存储并非发生在数据湖,而是在外围系统。
流式架构的适用场景就是预警,监控,对数据有有效期要求的情况。这些就是流式架构的主要内容。
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三个组件组成。
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从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中。
|
3) 判断44445端口是否被占用
|
4) 启动flume配置文件
注意:末尾的“ \”表示下一行的连接下一行的内容
|
-Dflume.root.logger==INFO,console #打印控制台目录的
5) 使用telnet工具登录本机
|
6) 使用telnet工具向本机的4445端口发送内容
发送:
接收:
六。案例二:实时读取本地文件到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
补充:
注意:
- 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) 执行监控配置
|
4) 执行完命令之后,HDFS中没有出现这个文件
5)改变文件之后,查看结果
当改变文件/opt/Andy之后,在http://bigdata111:50070/页面中从出现了文件 【/flume/05/Andy-.1570624975346.tmp】
这个时候没有满一小时,文件名中含有tmp。等过了1小时之后,这个tmp会被去掉。【但是事实好像不是这样】
6)在过了一段时间之后,大概10分钟。变成了
7)测试关于hdfs的一些属性(roll)
rollInterval 表示 hdfs sink间隔多长将临时文件滚动成最终目标文件,并新打开一个临时文件来写入数据;滚动文件即指将HDFS上生成的以.tmp结尾的临时文件转换为实际存储文件。默认值:30。
当我们运行命令的时候,生成一个tmp文件,这里保存的是监控的文件的原有内容。由于我们设置的rollInterval是300秒,查看测试结果的变化,经过300秒,tmp文件临时文件转化为了最终文件。然后生成了新的tmp文件。新的文件中只有新添加的数据,没有原有的数据。
(1)Andy文件
(2)改动
将flume-hdfs.conf的这两个属性的值进行改动
a2.sinks.k2.hdfs.rollInterval = 300
a2.sinks.k2.hdfs.roundUnit = minute
(3)运行文件
生成了文件Andy-.1573130714695.tmp,查看文件Andy-.1573130714695.tmp
(4)经过1分钟查看变化
经过了1分钟,没有变化。
(5)5分钟(300秒)后临时文件滚动成了最终文件。
(6)追加内容,产生了新的tmp文件
(7)再次追加内容,没有产生新文件。(这次的追加“2”和追加“1”的操作只隔了5秒)
(8)查看Andy-.1573131205163.tmp文件,只有我们添加的内容。而Andy-.1573130714695文件中只有原来的内容。
8)测试关于hdfs的一些属性(round)
当设置了round、roundValue、roundUnit参数,需要在sink指定的HDFS路径上指定按照时间生成的目录的格式,当有需求(我理解的是文件变动)。每隔roundValue的时间【这个例子是1分钟】,就在HDFS目录上生成一个目录,里面存放这1分钟内采集到的数据。
最开始生成的hdfs文件存储的是要监控文件的全部内容。之后在追加以后生成的hdfs文件,只保存了追加的数据。
(1)Andy文件
(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秒,生成一个最终文件。继续观察,又经过了两分钟,没有任何变化,没有产生新文件。
(4)追加内容
我们设置的hdfs路径是【/flume/分钟数】。产生新的tmp文件 Andy-.1573132979481.tmp,它的文件夹是22。相隔6秒,再次追加,然后产生了新文件Andy-.1573132984425.tmp,它的文件是23。看起来是如果是在不同的分钟数下,每添加一次就会产生一个新文件。这两个临时文件经过30秒【因为roolInterval默认值:30。】,变成了最终文件。
(5)继续追加内容
我们在23分钟这个时间内进行了两次文件添加,但是只产生了一个文件Andy-.1573133411209.tmp。
七。案例三:实时读取目录文件到HDFS
目标:使用flume监听整个目录的文件
分步实现:
1) 创建配置文件flume-dir.conf
|
2) 执行测试:执行如下脚本后,请向upload文件夹中添加文件试试
|
或者
[root@bigdata112 flume-1.8.0]# bin/flume-ng agent --conf conf/ --name a3 --conf-file jobconf/flume-dir.conf
3) 执行命令后在upload文件夹中创建A 和 B文件夹。
4)查看结果
5) 过了一段时间变成了这样(不超过10分钟)
尖叫提示:
1) 不要在监控目录中创建并持续修改文件
2) 上传完成的文件会以.COMPLETED结尾
3) 被监控文件夹每500毫秒扫描一次文件变动