flume详解 从原理到应用

第一章 flume概述

1.1 flume定义
flume是cloudera提供的一个高可用,高可靠,分布式的海量日志采集、聚合和传输的系统。flume基于流式架构,灵活简单。
在这里插入图片描述
flume最主要的作用:实时读取服务器本地磁盘的数据,将数据写入HDFS或kafka消息队列中。

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

1.2 flume基础架构
flume的组成架构如图所示:
在这里插入图片描述
1.2.1 agent
agent是一个jvm进程,他以事件的形式将数据从源头送至目的地。
agent主要有3个部分组成:source、channel、sink

1.2.2 source
source在flume agent组建中起到负责接收数据的作用。source组件可以处理各种类型、各种格式的日志数据,包括avro、exec、spooling directory、taildir、netcat、thrift、jms、legacy……。

1.2.3 sink
sink不断地轮询channel中的事件且批量地移除他们,并将在这些事件批量写入到存储或索引系统、或者被发送到另一个flume agent。
sink传输数据的目的地包括hdfs、logger、avro、file、hbase、kafka……。

1.2.4 channel
channel是位于source和sink之间的缓冲区。因此,channel允许source和sink运作在不同的速率上。channel是线程安全的,可以同时处理几个source的写入操作和几个sink的读取操作。也就是说,在一个flume当中可以同时有多个source,多个channel或者多个sink。
flume自带两种channel:memory channelfile channel
memory channel是内存中的队列。memory channel在不需要关心数据丢失的情况下适用。如果担心数据丢失,那么memory channel就不是一个好的选择,**由于在memory channel将事件存储在内存中,那么当程序死亡、机器宕机或者机器重启时都会有导致数据丢失的风险。**因此,memory也被称作,不稳定隧道。

file channel将所有事件写入到磁盘当中。因此在程序关闭或者机器宕机的情况下不会丢失数据。因此,file channel也被称作为持久化隧道。

1.2.5 event
传输单元,flume传输数据的基本单元,以event事件的形式将数据从源头送至目的地。event由header和body两部分组成,header用来存放改event的一些属性值,为k—v结构,body用来存放该条数据,形式为字节数组。
在这里插入图片描述
第二章 flume入门

2.1 flume安装部署

2.1.1 安装地址

(1)Flume官网地址:http://flume.apache.org/
(2)文档查看地址:http://flume.apache.org/FlumeUserGuide.html
(3)下载地址:http://archive.apache.org/dist/flume/

2.1.2 安装部署

(1)将apache-flume-1.9.0-bin.tar.gz上传到linux的/opt/software目录下
(2)解压apache-flume-1.9.0-bin.tar.gz到/opt/module/目录下

[atguigu@hadoop101 software]$ tar -zxf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/

(3)修改apache-flume-1.9.0-bin的名称为flume(这一步是为了以后写该路径时更加简洁方便

[atguigu@hadoop101 module]$ mv /opt/module/apache-flume-1.9.0-bin /opt/module/flume

(4)将lib文件夹下的guava-11.0.2.jar删除以兼容Hadoop 3.1.3

[atguigu@hadoop101 lib]$  rm /opt/module/flume/lib/guava-11.0.2.jar

2.2 flume入门案例

2.2.1 监控端口数据官方案例

1)案例需求:
使用Flume监听一个端口,收集该端口数据,并打印到控制台。

2)需求分析:
在这里插入图片描述
3)实现步骤:

(1)安装netcat工具

[atguigu@hadoop101 software]$ sudo yum install -y nc

(2)判断44444端口是否被占用
(3)创建Flume Agent配置文件flume-netcat-logger.conf
(4)在flume目录下创建job文件夹并进入job文件夹。

[atguigu@hadoop101 flume]$ mkdir job
[atguigu@hadoop101 flume]$ cd job/

(5)在job文件夹下创建Flume Agent配置文件flume-netcat-logger.conf。

[atguigu@hadoop101 job]$ vim flume-netcat-logger.conf

(6)在flume-netcat-logger.conf文件中添加如下内容。

# Name the components on this agent             //配置agent,将此agent命名为a1
a1.sources = r1                                 //将此agent的source命名为r1
a1.sinks = k1                                   //将此agent的sink命名为k1
a1.channels = c1                                //将此agent的channel命名为c1

# Describe/configure the source                 //配置source
a1.sources.r1.type = netcat                     //定义source的类型为netcat
a1.sources.r1.bind = localhost                  //表明当前的agent a1监听的主机
a1.sources.r1.port = 44444                      //表明当前agent a1监听的端口号

# Describe the sink                             //配置sink
a1.sinks.k1.type = logger                       //表示a1的输出目的地是控制台logger类型

# Use a channel which buffers events in memory  //配置channel
a1.channels.c1.type = memory                    //表明当前agent的channel类型为memory channel
a1.channels.c1.capacity = 1000                  //表明当前agent的memory channel的总容量为1000个event事件
a1.channels.c1.transactionCapacity = 100        //表明当前agent的channel收集到100个event事件过后再去提交事务

# Bind the source and sink to the channel       //配置source、sink和channel之间的联系关系
a1.sources.r1.channels = c1              //表示将r1和c1连接起来
a1.sinks.k1.channel = c1                 //表示将k1和c1连接起来

(7)先开启flume监听端口

[atguigu@hadoop101 flume]$ bin/flume-ng agent -c conf/ -n a1 -f job/netcat2-flume-logger.conf  -Dflume.root.logger=INFO,console

特别注意:代码中INFO,console之间是英文逗号,而非中文逗号或英文句号

这里说明一下flume-ng代表的意义:
说到flume-ng,就不得不提到以前的flume-og,现在基本已经不再用flume-og
在 OG 版本中,Flume 的使用稳定性依赖 zookeeper。它需要 zookeeper 对其多类节点(agent、collector、master)的工作进行管理,尤其是在集群中配置多个 master 的情况下。当然,OG也可以用内存的方式管理各类节点的配置信息,但是需要用户能够忍受在机器出现故障时配置信息出现丢失。所以说 OG 的稳定行使用是依赖zookeeper 的。
而在 NG 版本中,节点角色的数量由 3 缩减到 1,不存在多类角色的问题,所以就不再需要 zookeeper 对各类节点协调的作用了,由此脱离了对 zookeeper 的依赖。由于 OG 的稳定使用对 zookeeper 的依赖表现在整个配置和使用过程中,这就要求用户掌握对 zookeeper 集群的搭建及其使用。

参数说明:
–conf/-c:表示配置文件存储在conf/目录
–name/-n:表示给agent起名为a1
–conf-file/-f:flume本次启动读取的配置文件是在job文件夹下的flume-telnet.conf文件。
-Dflume.root.logger=INFO,console :-D表示flume运行时动态修改flume.root.logger参数属性值,并将控制台日志打印级别设置为INFO级别。日志级别包括:log、info、warn、error。

(8)使用netcat工具向本机的44444端口发送内容
在这里插入图片描述

(9)在Flume监听页面观察接收数据情况
在这里插入图片描述
2.2.2 实时监控单个追加文件

1)案例需求:实时监控hive日志,并上传到hdfs中
2)需求分析
在这里插入图片描述
3)实现步骤:

(1)Flume要想将数据输出到HDFS,依赖Hadoop相关jar包
检查/etc/profile.d/my_env.sh文件,确认Hadoop和Java环境变量配置正确

JAVA_HOME=/opt/module/jdk1.8.0_212
HADOOP_HOME=/opt/module/ha/hadoop-3.1.3

PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

export PATH JAVA_HOME HADOOP_HOME

(2)创建file-flume-hdfs.conf文件
创建文件

[atguigu@hadoop101 job]$ vim flile-flume-hdfs.conf

添加如下内容

# Name the components on this agent
a2.sources = r2
a2.sinks = k2
a2.channels = c2

# Describe/configure the source
a2.sources.r2.type = exec
a2.sources.r2.command = tail -F /opt/module/hive/logs/hive.log  //从hive日志中获取到数据

# Describe the sink
a2.sinks.k2.type = hdfs                                         //定义sink为hdfs类型
a2.sinks.k2.hdfs.path = hdfs://hadoop102:8020/flume/%Y%m%d/%H   //数据上传到hdfs上的路径
#上传文件的前缀
a2.sinks.k2.hdfs.filePrefix = logs-
#是否按照时间滚动文件夹
a2.sinks.k2.hdfs.round = true
#多少时间单位创建一个新的文件夹
a2.sinks.k2.hdfs.roundValue = 1
#重新定义时间单位
a2.sinks.k2.hdfs.roundUnit = hour
#是否使用本地时间戳
a2.sinks.k2.hdfs.useLocalTimeStamp = true
#积攒多少个Event才flush到HDFS一次
a2.sinks.k2.hdfs.batchSize = 100
#设置文件类型,可支持压缩
a2.sinks.k2.hdfs.fileType = DataStream
#多久生成一个新的文件
a2.sinks.k2.hdfs.rollInterval = 60
#设置每个文件的滚动大小
a2.sinks.k2.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a2.sinks.k2.hdfs.rollCount = 0

# Use a channel which buffers events in memory
a2.channels.c2.type = memory
a2.channels.c2.capacity = 1000
a2.channels.c2.transactionCapacity = 100

# Bind the source and sink to the channel
a2.sources.r2.channels = c2
a2.sinks.k2.channel = c2

(3)运行flume

[atguigu@hadoop101 flume]$ bin/flume-ng agent --conf conf/ --name a2 --conf-file job/flume-file-hdfs.conf

(4)开启Hadoop和Hive并操作Hive产生日志

[atguigu@hadoop101 hadoop-2.7.2]$ sbin/start-dfs.sh
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-yarn.sh

[atguigu@hadoop101 hive]$ bin/hive
hive (default)>

(5)在HDFS上查看文件。
在这里插入图片描述
2.2.3 实时监控目录下多个新文件
1)案例需求:使用Flume监听整个目录的文件,并上传至HDFS
2)需求分析:
在这里插入图片描述
3)实现步骤:
(1)创建配置文件spooldir-dir-hdfs.conf
创建文件

[atguigu@hadoop101 job]$ vim spooldir-dir-hdfs.conf

添加如下内容

a3.sources = r3
a3.sinks = k3
a3.channels = c3

# Describe/configure the source
a3.sources.r3.type = spooldir                      //声明source的类型为spooldir
a3.sources.r3.spoolDir = /opt/module/flume/upload  //声明监控的文件目录
a3.sources.r3.fileSuffix = .COMPLETED              //声明文件上传完后,加上此后缀
a3.sources.r3.fileHeader = true
#忽略所有以.tmp结尾的文件,不上传
a3.sources.r3.ignorePattern = ([^ ]*\.tmp)

# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://hadoop102:8020/flume/upload/%Y%m%d/%H
#上传文件的前缀
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
#设置文件类型,可支持压缩
a3.sinks.k3.hdfs.fileType = DataStream
#多久生成一个新的文件
a3.sinks.k3.hdfs.rollInterval = 60
#设置每个文件的滚动大小大概是128M
a3.sinks.k3.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a3.sinks.k3.hdfs.rollCount = 0

# Use a channel which buffers events in memory
a3.channels.c3.type = memory
a3.channels.c3.capacity = 1000
a3.channels.c3.transactionCapacity = 100

# Bind the source and sink to the channel
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3

(3)向upload文件夹中添加文件
在/opt/module/flume目录下创建upload文件夹

[atguigu@hadoop101 flume]$ mkdir upload

(4)查看HDFS上的数据

2.2.4 实时监控目录下的多个追加文件

Exec source适用于监控一个实时追加的文件,不能实现断点续传;Spooldir Source适合用于同步新文件,但不适合对实时追加日志的文件进行监听并同步;而Taildir Source适合用于监听多个实时追加的文件,并且能够实现断点续传。

1)案例需求:使用Flume监听整个目录的实时追加文件,并上传至HDFS

2)需求分析:
在这里插入图片描述
3)3)实现步骤:
(1)创建配置文件flume-taildir-hdfs.conf
创建一个文件

[atguigu@hadoop101 job]$ vim flume-taildir-hdfs.conf

添加内容

a3.sources = r3
a3.sinks = k3
a3.channels = c3

# Describe/configure the source
a3.sources.r3.type = TAILDIR
a3.sources.r3.positionFile = /opt/module/flume/tail_dir.json
a3.sources.r3.filegroups = f1 f2
a3.sources.r3.filegroups.f1 = /opt/module/flume/files/.*file.*
a3.sources.r3.filegroups.f2 = /opt/module/flume/files2/.*log.*

# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://hadoop102:8020/flume/upload2/%Y%m%d/%H
#上传文件的前缀
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
#设置文件类型,可支持压缩
a3.sinks.k3.hdfs.fileType = DataStream
#多久生成一个新的文件
a3.sinks.k3.hdfs.rollInterval = 60
#设置每个文件的滚动大小大概是128M
a3.sinks.k3.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a3.sinks.k3.hdfs.rollCount = 0

# Use a channel which buffers events in memory
a3.channels.c3.type = memory
a3.channels.c3.capacity = 1000
a3.channels.c3.transactionCapacity = 100

# Bind the source and sink to the channel
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3

(2)启动监控文件夹命令

[atguigu@hadoop101 flume]$ bin/flume-ng agent --conf conf/ --name a3 --conf-file job/flume-taildir-hdfs.conf

(3)向files文件夹中追加内容
在/opt/module/flume目录下创建files文件夹

[atguigu@hadoop101 flume]$ mkdir files

向files文件夹中添加文件

[atguigu@hadoop101 files]$ echo hello >> file1.txt
[atguigu@hadoop101 files]$ echo atguigu >> file2.txt

(4)查看HDFS上的数据

Taildir说明:
Taildir Source维护了一个json格式的position File,其会定期的往position File中更新每个文件读取到的最新的位置,因此能够实现断点续传。Position File的格式如下:

	{"inode":2496272,"pos":12,"file":"/opt/module/flume/files/file1.txt"}
{"inode":2496275,"pos":12,"file":"/opt/module/flume/files/file2.txt"}

注:Linux中储存文件元数据的区域就叫做inode,每个inode都有一个号码,操作系统用inode号码来识别不同的文件,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。

2.2.5 本章总结

Exec source 适用于监控一个实时追加的文件,但不能保证数据不丢失;
Spooldir Source 能够保证数据不丢失,且能够实现断点续传,但延迟较高,不能实时监控;
Taildir Source 既能够实现断点续传,又可以保证数据不丢失,还能够进行实时监控。

第三章 flume进阶

3.1 flume事务

在这里插入图片描述
3.2 flume agent内部原理

在这里插入图片描述
重要组件:

1)channel selector:
channelselector的作用就是选出event将要发往哪个channel。其中有两种类型,分别是replicating(复制)和multiplexing(多路复用)
replicatingselector会将同一个event发往所有的channel,multiplexing会根据相应的原则,选择性的将event发往指定的channel

2)sinkprocessor
sinkprocessor一共有三种类型,分别是defaultsinkprocessor、loadbalancingsink和failoversinkprocessor
defaultsinkprocessor对应的是单个的sink,loadbalancingsinkprocessor和failoversinkprocessor对应的是sinkgroup,loadbalancingsinkprocessor可以实现负载均衡的功能,failoversinkprocessor可以错误恢复的功能。

3.3 flume拓扑结构

3.3.1 简单串联

在这里插入图片描述
这种模式是将多个flume顺序连接起来,从最初的source开始进行数据的采集一路传送到sink目的地的存储系统。此模式不建议串联桥接过多的flume数量,flume数量过多不仅会影响传输速率,而且一旦传输过程中某个节点flume宕机,会影响整个传输系统。

3.3.2 复制和多路复用

在这里插入图片描述
flume支持将一个数据来源,通过事件流向一个或者多个目的地。这种模式可以将相同数据复制到多个channel中,或者将不同的数据分发传输到不同的channel中,与此同时,sink也可以选择传送到不同的目的地当中。

3.3.3 负载均衡和故障转移

在这里插入图片描述
Flume支持使用将多个sink逻辑上分到一个sink组,sink组配合不同的SinkProcessor可以实现负载均衡和错误恢复的功能。

3.3.4 聚合

在这里插入图片描述
这种模式是我们最常见的,也非常实用,日常web应用通常分布在上百个服务器,大者甚至上千个、上万个服务器。产生的日志,处理起来也非常麻烦。用flume的这种组合方式能很好的解决这一问题,每台服务器部署一个flume采集日志,传送到一个集中收集日志的flume,再由此flume上传到hdfs、hive、hbase等,进行日志分析。

3.4 flume企业开发案例

3.4.1 复制和多路复用

在实际工作当中,企业的需要常常不限于只使用一个flume作为数据的传输通道。从数据采集源到目的地通常是需要多个flume组个使用,解决需求的同时,达到更高的传输效率。

1)案例需求
使用flume-1监控单个文件变动,flume-1将变动内容传递给flume-2,flume-2负责存储到hdfs上面。同时flume-1通过另一个通道将内容传递给flume-3,flume-3的职责是将数据传输到本地的文件当中。

2)需求分析
在这里插入图片描述
3)实现步骤
(1)准备工作
在opt/module/flume/job目录下创建group文件夹

[atguigu@hadoop101 job]$ cd group

在/opt/module/flume/datas/目录下创建flume3文件夹

[atguigu@hadoop101 datas]$ mkdir flume3

(2)创建exec-memory-avro.conf
配置1个接收日志的source和两个channel、两个sink,分别输送给avro-memory-hdfs和avro-memory-local

编辑配置文件

[atguigu@hadoop101 group]$ vim exec-memory-avro.conf

添加如下内容

# Name the components on this agent
a1.sources = r1
a1.sinks = k1 k2
a1.channels = c1 c2
# 将数据流复制给所有channel
a1.sources.r1.selector.type = replicating

# Describe/configure the source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /opt/module/hive/logs/hive.log
a1.sources.r1.shell = /bin/bash -c

# Describe the sink
# sink端的avro是一个数据发送者
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = hadoop101
a1.sinks.k1.port = 4141

a1.sinks.k2.type = avro
a1.sinks.k2.hostname = hadoop101
a1.sinks.k2.port = 4142

# Describe the channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.channels.c2.type = memory
a1.channels.c2.capacity = 1000
a1.channels.c2.transactionCapacity = 100

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

(3)创建avro-memory-hdfs.conf
配置此flume的source衔接上一个flume的sink,此flume的输出是hdfs的sink

创建配置文件

[atguigu@hadoop101 group]$ vim avro-memory-hdfs.conf

添加如下内容

# Name the components on this agent
a2.sources = r1
a2.sinks = k1
a2.channels = c1

# Describe/configure the source
# source端的avro是一个数据接收服务
a2.sources.r1.type = avro
a2.sources.r1.bind = hadoop101
a2.sources.r1.port = 4141

# Describe the sink
a2.sinks.k1.type = hdfs
a2.sinks.k1.hdfs.path = hdfs://hadoop101:8020/flume2/%Y%m%d/%H
#上传文件的前缀
a2.sinks.k1.hdfs.filePrefix = flume2-
#是否按照时间滚动文件夹
a2.sinks.k1.hdfs.round = true
#多少时间单位创建一个新的文件夹
a2.sinks.k1.hdfs.roundValue = 1
#重新定义时间单位
a2.sinks.k1.hdfs.roundUnit = hour
#是否使用本地时间戳
a2.sinks.k1.hdfs.useLocalTimeStamp = true
#积攒多少个Event才flush到HDFS一次
a2.sinks.k1.hdfs.batchSize = 100
#设置文件类型,可支持压缩
a2.sinks.k1.hdfs.fileType = DataStream
#多久生成一个新的文件
a2.sinks.k1.hdfs.rollInterval = 600
#设置每个文件的滚动大小大概是128M
a2.sinks.k1.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a2.sinks.k1.hdfs.rollCount = 0

# Describe the channel
a2.channels.c1.type = memory
a2.channels.c1.capacity = 1000
a2.channels.c1.transactionCapacity = 100

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

(4)创建avro-memory-local.conf
配置此flume的source衔接上一个flume的sink,此flume输出端是本地。

编辑配置文件

[atguigu@hadoop101 group]$ vim avro-memory-local.conf

添加如下内容

# Name the components on this agent
a3.sources = r1
a3.sinks = k1
a3.channels = c2

# Describe/configure the source
a3.sources.r1.type = avro
a3.sources.r1.bind = hadoop101
a3.sources.r1.port = 4142

# Describe the sink
a3.sinks.k1.type = file_roll
a3.sinks.k1.sink.directory = /opt/module/flume/datas/flume3

# Describe the channel
a3.channels.c2.type = memory
a3.channels.c2.capacity = 1000
a3.channels.c2.transactionCapacity = 100

# Bind the source and sink to the channel
a3.sources.r1.channels = c2
a3.sinks.k1.channel = c2

注意:输出的本地目录必须是已经存在的目录,如果该目录不存在,并不会创建新的目录。

(6)启动hadoop和hive

[atguigu@hadoop101 hadoop-2.7.2]$ sbin/start-dfs.sh
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-yarn.sh

[atguigu@hadoop101 hive]$ bin/hive
hive (default)>

(7)查看hdfs上是否接收到数据
在这里插入图片描述
(8)检查/opt/module/datas/flume3目录中数据
在这里插入图片描述
3.4.2 聚合

1)案例需求:
hadoop101上的Flume-1监控文件/opt/module/hive/logs/hive.log
hadoop102上的Flume-2监控某一个端口的数据流,
Flume-1与Flume-2将数据发送给hadoop103上的Flume-3,Flume-3将最终数据打印到控制台。

2)需求分析
在这里插入图片描述
3)实现步骤
(1)准备工作
在hadoop101、hadoop102以及hadoop103三台虚拟机的/opt/module/flume/job目录下创建一个group3文件夹。

[atguigu@hadoop101 job]$ mkdir group3
[atguigu@hadoop102 job]$ mkdir group3
[atguigu@hadoop103 job]$ mkdir group3

(2)创建flume1-logger-flume.conf
配置Source用于监控hive.log文件,配置Sink输出数据到下一级Flume。
在hadoop101上编辑配置文件

[atguigu@hadoop101 group3]$ vim flume1-logger-flume.conf

添加如下内容

# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = exec        
a1.sources.r1.command = tail -F /opt/module/hive/logs/hive.log  //指定监控hive日志文件
a1.sources.r1.shell = /bin/bash -c

# Describe the sink
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = hadoop103                                //指定sink输出到的目的地
a1.sinks.k1.port = 4141                                         //指定输出端口

# Describe the channel
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

(3)创建flume2-netcat-flume.conf
配置Source监控端口44444数据流,配置Sink数据到下一级Flume:
在hadoop102上编辑配置文件

[atguigu@hadoop102 group3]$ vim flume2-netcat-flume.conf

添加如下内容

# Name the components on this agent
a2.sources = r1
a2.sinks = k1
a2.channels = c1

# Describe/configure the source
a2.sources.r1.type = netcat
a2.sources.r1.bind = hadoop102
a2.sources.r1.port = 44444                        //指定数据来源的监听窗口

# Describe the sink
a2.sinks.k1.type = avro
a2.sinks.k1.hostname = hadoop103
a2.sinks.k1.port = 4141                           //指定sink的输出端口

# Use a channel which buffers events in memory
a2.channels.c1.type = memory
a2.channels.c1.capacity = 1000
a2.channels.c1.transactionCapacity = 100

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

(4)创建flume3-flume-logger.conf
配置source用于接收flume1与flume2发送过来的数据流,最终合并后sink到控制台。
在hadoop103上编辑配置文件

[atguigu@hadoop103 group3]$ touch flume3-flume-logger.conf
[atguigu@hadoop103 group3]$ vim flume3-flume-logger.conf

添加如下内容

# Name the components on this agent
a3.sources = r1
a3.sinks = k1
a3.channels = c1

# Describe/configure the source
a3.sources.r1.type = avro
a3.sources.r1.bind = hadoop103
a3.sources.r1.port = 4141

# Describe the sink
# Describe the sink
a3.sinks.k1.type = logger

# Describe the channel
a3.channels.c1.type = memory
a3.channels.c1.capacity = 1000
a3.channels.c1.transactionCapacity = 100

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

(5)执行配置文件
分别开启对应配置文件:flume3-flume-logger.conf,flume2-netcat-flume.conf,flume1-logger-flume.conf。

[atguigu@hadoop103 flume]$ bin/flume-ng agent --conf conf/ --name a3 --conf-file job/group3/flume3-flume-logger.conf -Dflume.root.logger=INFO,console

[atguigu@hadoop101 flume]$ bin/flume-ng agent --conf conf/ --name a2 --conf-file job/group3/flume1-logger-flume.conf

[atguigu@hadoop102 flume]$ bin/flume-ng agent --conf conf/ --name a1 --conf-file job/group3/flume2-netcat-flume.conf

(6)启动hive,并在hive中进行相应的操作

(7)在hadoop101上向44444端口发送数据

[atguigu@hadoop101 flume]$ telnet hadoop101 44444

(8)检查hadoop103上数据

3.5 第三章总结

1)通过这一章的学习,我们可以渐渐发现,学习flume,其实就是在学习flume的配置文件,几乎设计的所有flume组件都是在对配置文件进行相应的配置来解决用户的需求。
2)在写多个flume组件的配置文件时,需要注意的是port端口号的配置,大致的规律就是前者的sink端口对应后者接收的flume的source的端口号。
3)在两个flume之间,多个sink可以对接一个source,一个sink无法对接多个source。

第四章 自定义interceptor

1)interceptor原理及作用

flume是以多种组件形成的一个框架,最最常用的三种组件有:source、channel、sink。这三个组件分别来完成事件(event)数据的“收集”、“传递”、“写入”的功能,一般需求都可以通过这三种组件来满足其需求,但是在一些特殊场景下,我们需要在event数据流向中间,加入一些自定义的逻辑,这时候intercept组件就发挥了作用。
拦截器设置在source和channel之间,source接收到后,在写入channel之前,拦截器都可以进行转换或者删除这些事件。每个拦截器只处理同一个source接收到的事件。flume内部默认设置了很多intercept组件,同时也支持自定义拦截器。

2) 案例需求

使用Flume采集服务器本地日志,需要按照日志类型的不同,将不同种类的日志发往不同的分析系统。

3)需求分析

在实际的开发中,一台服务器产生的日志类型可能有很多种,不同类型的日志可能需要发送到不同的分析系统。此时会用到Flume拓扑结构中的Multiplexing结构,Multiplexing的原理是,根据event中Header的某个key的值,将不同的event发送到不同的Channel中,所以我们需要自定义一个Interceptor,为不同类型的event的Header中的key赋予不同的值
在该案例中,我们以端口数据模拟日志,以数字(单个)和字母(单个)模拟不同类型的日志,我们需要自定义interceptor区分数字和字母,将其分别发往不同的分析系统(Channel)。
在这里插入图片描述

3)实现步骤
(1)创建一个maven项目,并引入一下依赖。

<dependency>
    <groupId>org.apache.flume</groupId>
    <artifactId>flume-ng-core</artifactId>
    <version>1.9.0</version>
</dependency>

(2)定义CustomInterceptor类并实现Interceptor接口。

package com.atguigu.flume.interceptor;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.util.List;

public class CustomInterceptor implements Interceptor {         //实现interceptor接口


    @Override
    public void initialize() {

    }

    @Override
    public Event intercept(Event event) {                        //单个事件拦截

        byte[] body = event.getBody();                           //获取事件的body
        if (body[0] < 'z' && body[0] > 'a') {                    //判断event中的body里面的内容是否是a-z的字母
            event.getHeaders().put("type", "letter");            //如果是,则添加type标签,添加为letter
        } else if (body[0] > '0' && body[0] < '9') {             //判断event中的body里面的内容是否是0-9的数字
            event.getHeaders().put("type", "number");            //如果是,则添加type标签,添加为number
        }
        return event;

    }

    @Override
    public List<Event> intercept(List<Event> events) {            //批量事件拦截
        for (Event event : events) {                              //遍历每一个event
            intercept(event);
        }
        return events;
    }

    @Override
    public void close() {

    }

    public static class Builder implements Interceptor.Builder {

        @Override
        public Interceptor build() {
            return new CustomInterceptor();
        }

        @Override
        public void configure(Context context) {
        }
    }
}

(3)编辑flume配置文件
为hadoop101上的Flume1配置1个netcat source,1个sink group(2个avro sink),并配置相应的ChannelSelector和interceptor。

# Name the components on this agent
a1.sources = r1
a1.sinks = k1 k2
a1.channels = c1 c2

# Describe/configure the source
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = com.atguigu.flume.interceptor.CustomInterceptor$Builder  //配置的拦截器文件的全类名
a1.sources.r1.selector.type = multiplexing                        //指定选择器为multiplexing类型
a1.sources.r1.selector.header = type
a1.sources.r1.selector.mapping.letter = c1
a1.sources.r1.selector.mapping.number = c2
# Describe the sink
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = hadoop102
a1.sinks.k1.port = 4141

a1.sinks.k2.type=avro
a1.sinks.k2.hostname = hadoop103
a1.sinks.k2.port = 4242

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

# Use a channel which buffers events in memory
a1.channels.c2.type = memory
a1.channels.c2.capacity = 1000
a1.channels.c2.transactionCapacity = 100


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

为hadoop102上的Flume4配置一个avro source和一个logger sink。

a1.sources = r1
a1.sinks = k1
a1.channels = c1

a1.sources.r1.type = avro
a1.sources.r1.bind = hadoop102
a1.sources.r1.port = 4141

a1.sinks.k1.type = logger

a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.sinks.k1.channel = c1
a1.sources.r1.channels = c1

为hadoop103上的Flume3配置一个avro source和一个logger sink。

a1.sources = r1
a1.sinks = k1
a1.channels = c1

a1.sources.r1.type = avro
a1.sources.r1.bind = hadoop103
a1.sources.r1.port = 4242

a1.sinks.k1.type = logger

a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.sinks.k1.channel = c1
a1.sources.r1.channels = c1

(4)分别在hadoop101,hadoop102,hadoop103上启动flume进程,注意先后顺序。
(5)在hadoop102使用netcat向localhost:44444发送字母和数字。
(6)观察hadoop103和hadoop104打印的日志,体会拦截器和mutiplexing选择器在其中发挥的作用。

第五章 企业真实面试题

5.1 你是如何实现Flume数据传输的监控的

使用第三方框架Ganglia实时监控Flume。

5.2 Flume的Source,Sink,Channel的作用?你们Source是什么类型?

1)作用
(1)Source组件是专门用来收集数据的,可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy
(2)Channel组件对采集到的数据进行缓存,可以存放在Memory或File中。
(3)Sink组件是用于把数据发送到目的地的组件,目的地包括Hdfs、Logger、avro、thrift、ipc、file、Hbase、solr、自定义。
2)我公司采用的Source类型为:
(1)监控后台日志:exec
(2)监控后台产生日志的端口:netcat

5.3 flume事务机制

Flume的事务机制(类似数据库的事务机制):Flume使用两个独立的事务分别负责从Soucrce到Channel,以及从Channel到Sink的事件传递。比如spooling directory source 为文件的每一行创建一个事件,一旦事务中所有的事件全部传递到Channel且提交成功,那么Soucrce就将该文件标记为完成。同理,事务以类似的方式处理从Channel到Sink的传递过程,如果因为某种原因使得事件无法记录,那么事务将会回滚。且所有的事件都会保持到Channel中,等待重新传递。

5.4 Flume采集数据会丢失吗?

根据Flume的架构原理,Flume是不可能丢失数据的,其内部有完善的事务机制,Source到Channel是事务性的,Channel到Sink是事务性的,因此这两个环节不会出现数据的丢失,唯一可能丢失数据的情况是Channel采用memoryChannel,agent宕机导致数据丢失,或者Channel存储数据已满,导致Source不再写入,未写入的数据丢失。

猜你喜欢

转载自blog.csdn.net/weixin_41929239/article/details/109681017