第 1 章 Flume 概述
1.1 Flume 定义
Flume 是 Cloudera 提供的一个高可用的,高可靠的,分布式的 海量日志采集、聚合和传
输的系统 。 Flume 基于流式架构,灵活简单。
为什么选用 Flume
Python 爬虫数据
Java 后台日志数据
服务器本地磁盘
文件夹
HDFS
Flume
Flume 最主要的作用就是,实时读取服务器本地磁盘的数据,将数据写入到 HDFS 。
Kafka
网络端口数据
1.2 Flume 基础架构
1.2.1 Agent
Agent 是一个 JVM 进程,它以事件的形式将数据从源头送至目的。
Agent 主要有 3 个部分组成, Source 、 Channel 、 Sink 。
1.2.2 Source
Source 是负责接收数据到 Flume Agent 的组件。Source 组件可以处理各种类型、各种
格式的日志数据,包括 avro 、thrift、 exec 、jms、 spooling directory 、 netcat 、 taildir 、
sequence generator、syslog、http、legacy。
1.2.3 Sink
Sink 不断地轮询 Channel 中的事件且批量地移除它们,并将这些事件批量写入到存储
或索引系统、或者被发送到另一个 Flume Agent。
Sink 组件目的地包括 hdfs 、 logger 、 avro 、thrift、ipc、 file 、 HBase 、solr、自定
义。
1.2.4 Channel
Channel 是位于 Source 和 Sink 之间的缓冲区。因此,Channel 允许 Source 和 Sink 运
作在不同的速率上。Channel 是线程安全的,可以同时处理几个 Source 的写入操作和几个
Sink 的读取操作。
Flume 自带两种 Channel: Memory Channel 和 File Channel 。
Memory Channel 是内存中的队列。Memory Channel 在不需要关心数据丢失的情景下适
用。如果需要关心数据丢失,那么 Memory Channel 就不应该使用,因为程序死亡、机器宕
机或者重启都会导致数据丢失。
File Channel 将所有事件写到磁盘。因此在程序关闭或机器宕机的情况下不会丢失数
据。
1.2.5 Event
传输单元,Flume 数据传输的基本单元,以 Event 的形式将数据从源头送至目的地。
Event 由 Header 和 Body 两部分组成,Header 用来存放该 event 的一些属性,为 K-V 结构,
Body 用来存放该条数据,形式为字节数组。
第 2 章 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@hadoop102 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@hadoop102 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@hadoop102 lib\]$ rm /opt/module/flume/lib/guava-
11.0.2.jar
**2.2 Flume** **入门案例**
**2.2.1** **监控端口数据官方案例**
**1)案例需求:**
使用 Flume 监听一个端口,收集该端口数据,并打印到控制台。
**2)需求分析:**
**---------------------------------------------------------------------------------------**
监听数据端口案例分析
2 Flume 监控本机的 44444 端口。
通过 Flume 的 source 端读取数据。
1 通过 netcat 工具向本机的 44444 端
口发送数据
3 Flume 将获取的数据通过
Sink 端写出到控制台
bin/flume-ng agent --conf conf/
--name a1
--conf-file job/flume-telnet.conf
-Dflume.root.logger==INFO,console
nc localhost 44444
44444 端口
控制台
hello
hello
测试命令
**3)实现步骤:**
(1)安装 netcat 工具
\[atguigu@hadoop102 software\]$ sudo yum install -y nc
(2)判断 44444 端口是否被占用
\[atguigu@hadoop102 flume-telnet\]$ sudo netstat -nlp \| grep 44444
(3)创建 Flume Agent 配置文件 flume-netcat-logger.conf
(4)在 flume 目录下创建 job 文件夹并进入 job 文件夹。
\[atguigu@hadoop102 flume\]$ mkdir job
\[atguigu@hadoop102 flume\]$ cd job/
(5)在 job 文件夹下创建 Flume Agent 配置文件 flume-netcat-logger.conf。
\[atguigu@hadoop102 job\]$ vim flume-netcat-logger.conf
(6)在 flume-netcat-logger.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
注:配置文件来源于官方手册 http://flume.apache.org/FlumeUserGuide.html
配置文件解析
# 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
**a1:** **表示** **agent** **的名称**
r1: 表示 a1 的 Source 的名称
k1: 表示 a1 的 Sink 的名称
c1: 表示 a1 的 Channel 的名称
表示 a1 的输入源类型为 netcat 端口类型
表示 a1 的监听的主机
表示 a1 的监听的端口号
表示 a1 的输出目的地是控制台 logger 类型
表示 a1 的 channel 类型是 memory 内存型
表示 a1 的 channel 总容量 1000 个 event
表示 a1 的 channel 传输时收集到了 100 条 event 以后再去提交事务
表示将 r1 和 c1 连接起来
表示将 k1 和 c1 连接起来
(7)先开启 flume 监听端口
第一种写法:
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a1 --conf-file job/flume-netcat-logger.conf -
Dflume.root.logger=INFO,console
第二种写法:
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent -c conf/ -n a1 -f
job/flume-netcat-logger.conf -Dflume.root.logger=INFO,console
参数说明:
--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 端口发送内容
\[atguigu@hadoop102 \~\]$ nc localhost 44444
hello
atguigu
(9)在 Flume 监听页面观察接收数据情况
**2.2.2** **实时监控单个追加文件**
**1)案例需求:实时监控 Hive 日志,并上传到 HDFS 中**
**2)需求分析** :
实时读取本地文件到 HDFS 案例
Hive 日志文件
/opt/module/hive/lo
gs/ hive.log
Flume 监控文件
HDFS
Hive 实时更新日志
Exec Source
HDFS Sink
Memory Channel
1 创建符合条件的 flume 配置文件
2 执行配置文件,开启监控
3 开启 Hive ,
生成日志
4 查看 HDFS
上数据
**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)创建 flume-file-hdfs.conf 文件
创建文件
\[atguigu@hadoop102 job\]$ vim flume-file-hdfs.conf
注:要想读取 Linux 系统中的文件,就得按照 Linux 命令的规则执行命令。由于 Hive
日志在 Linux 系统中所以读取文件的类型选择:exec 即 execute 执行的意思。表示执行
Linux 命令来读取文件。
添加如下内容
# 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
# Describe the sink
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs:// hadoop102:9820 /flume/%Y%m%d/%H
# 上传文件的前缀
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
**注意** :对于所有与时间相关的转义序列,Event Header 中必须存在以 "timestamp"的
key(除非 hdfs.useLocalTimeStamp 设置为 true,此方法会使用 TimestampInterceptor 自
动添加 timestamp)。
a3.sinks.k3.hdfs.useLocalTimeStamp = true
**---------------------------------------------------------------------------------------**
实时读取本地文件到 HDFS 案例
# 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
a2.sources.r2.shell = /bin/bash -c
# Describe the sink
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs://hadoop102:9000/flume/%Y%m%d/%H
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
a2.sinks.k2.hdfs.batchSize = 1000
a2.sinks.k2.hdfs.fileType = DataStream
a2.sinks.k2.hdfs.rollInterval = 60
a2.sinks.k2.hdfs.rollSize = 134217700
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
#上传文件的前缀
#是否按照时间滚动文件夹
#多少时间单位创建一个新的文件夹
#重新定义时间单位
#是否使用本地时间戳
#积攒多少个 Event 才 flush 到 HDFS 一次
#设置文件类型,可支持压缩
#多久生成一个新的文件
#设置每个文件的滚动大小
#文件的滚动与 Event 数量无关
#定义source
#定义sink
#定义channel
#定义source类型为exec可执行命令的
#执行shell脚本的绝对路径
(3)运行 Flume
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a2 --conf-file job/flume-file-hdfs.conf
(4)开启 Hadoop 和 Hive 并操作 Hive 产生日志
\[atguigu@hadoop102 hadoop-2.7.2\]$ sbin/start-dfs.sh
\[atguigu@hadoop103 hadoop-2.7.2\]$ sbin/start-yarn.sh
\[atguigu@hadoop102 hive\]$ bin/hive
hive (default)\>
(5)在 HDFS 上查看文件。
**2.2.3 实时监控目录下多个新文件**
**1)案例需求:使用 Flume 监听整个目录的文件,并上传至 HDFS**
**2)需求分析:**
**---------------------------------------------------------------------------------------**
实时读取目录文件到 HDFS 案例
被监控的目录
/opt/module/flume/
upload
Flume 监控目录
HDFS
待上传的文件
Spooldir Source
HDFS Sink
Memory Channel
1 创建符合条件的 flume 配置文件
2 执行配置文件,开启监控
3 向 upload 目
录中添加文件
4 查看 HDFS
上数据
5 查看 /opt/module/flume/upload
目录中上传的文件是否已经标记
为 .COMPLETED 结尾; .tmp 后缀
结尾文件没有上传。
**3)**
**3)实现步骤:**
(1)创建配置文件 flume-dir-hdfs.conf
创建一个文件
\[atguigu@hadoop102 job\]$ vim flume-dir-hdfs.conf
添加如下内容
a3.sources = r3
a3.sinks = k3
a3.channels = c3
# Describe/configure the source
a3.sources.r3.type = 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:9820 /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
实时读取目录文件到 HDFS 案例
a3.sources = r3
a3.sinks = k3
a3.channels = c3
# Describe/configure the source
a3.sources.r3.type = spooldir
a3.sources.r3.spoolDir = /opt/module/flume/upload
a3.sources.r3.fileSuffix = .COMPLETED
a3.sources.r3.fileHeader = true
a3.sources.r3.ignorePattern = (\[\^ \]\*\\.tmp)
# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path
=
hdfs://hadoop102:9000/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
a3.sinks.k3.hdfs.batchSize = 100
a3.sinks.k3.hdfs.fileType = DataStream
a3.sinks.k3.hdfs.rollInterval = 60
a3.sinks.k3.hdfs.rollSize = 134217700
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
#定义source
#定义sink
#定义channel
#定义source类型为目录
#定义监控目录
#定义文件上传完,后缀
#是否有文件头
#忽略所有以.tmp结尾的文件,不上传
#sink类型为hdfs
#文件上传到hdfs的路径
#上传文件到hdfs的前缀
#是否按时间滚动文件
#多少时间单位创建一个新的文件夹
#重新定义时间单位
#是否使用本地时间戳
#积攒多少个Event才flush到HDFS一次
#设置文件类型,可支持压缩
#多久生成新文件
#多大生成新文件
#多少event生成新文件
(2)启动监控文件夹命令
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a3 --conf-file job/flume-dir-hdfs.conf
说明: 在使用 Spooling Directory Source 时,不要在监控目录中创建并持续修改文
件;上传完成的文件会以.COMPLETED 结尾;被监控文件夹每 500 毫秒扫描一次文件变动。
(3)向 upload 文件夹中添加文件
在/opt/module/flume 目录下创建 upload 文件夹
\[atguigu@hadoop102 flume\]$ mkdir upload
向 upload 文件夹中添加文件
\[atguigu@hadoop102 upload\]$ touch atguigu.txt
\[atguigu@hadoop102 upload\]$ touch atguigu.tmp
\[atguigu@hadoop102 upload\]$ touch atguigu.log
(4)查看 HDFS 上的数据
**---------------------------------------------------------------------------------------**
**2.2.4 实时监控目录下的多个追加文件**
Exec source 适用于监控一个实时追加的文件,不能实现断点续传;Spooldir Source
适合用于同步新文件,但不适合对实时追加日志的文件进行监听并同步;而 Taildir Source
适合用于监听多个实时追加的文件,并且能够实现断点续传。
**1)案例需求:使用 Flume 监听整个目录的实时追加文件,并上传至 HDFS**
**2)需求分析:**
实时读取目录文件到 HDFS 案例
被监控的目录
/opt/module/flume/ files
Flume 监控目录
HDFS
Taildir Source
HDFS Sink
Memory Channel
1 创建符合条件的 flume 配置文件
2 执行配置文件,开启监控
4 查看 HDFS
上数据
3. 向监控文件追加内容
echo hello \>\> files/file1.txt
echo hello \>\> files/file2.txt
**3)**
**3)实现步骤:**
(1)创建配置文件 flume-taildir-hdfs.conf
创建一个文件
\[atguigu@hadoop102 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:9820 /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
实时读取目录文件到 HDFS 案例
a3.sources = r3
a3.sinks = k3
a3.channels = c3
# Describe/configure the source
a2.sources.r2.type = TAILDIR
a2.sources.r2.positionFile = /opt/module/flume/tail_dir.json
a2.sources.r2.filegroups = f1
a2.sources.r2.filegroups.f1 = /opt/module/flume/files/file\*
# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path
=
hdfs://hadoop102:9000/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
a3.sinks.k3.hdfs.batchSize = 100
a3.sinks.k3.hdfs.fileType = DataStream
a3.sinks.k3.hdfs.rollInterval = 60
a3.sinks.k3.hdfs.rollSize = 134217700
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
#定义source
#定义sink
#定义channel
#定义source类型
#定义监控目录文件
#指定position_file位置
#sink类型为hdfs
#文件上传到hdfs的路径
#上传文件到hdfs的前缀
#是否按时间滚动文件
#多少时间单位创建一个新的文件夹
#重新定义时间单位
#是否使用本地时间戳
#积攒多少个Event才flush到HDFS一次
#设置文件类型,可支持压缩
#多久生成新文件
#多大生成新文件
#多少event生成新文件
(2)启动监控文件夹命令
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a3 --conf-file job/flume-taildir-hdfs.conf
(3)向 files 文件夹中追加内容
在/opt/module/flume 目录下创建 files 文件夹
\[atguigu@hadoop102 flume\]$ mkdir files
**---------------------------------------------------------------------------------------**
向 upload 文件夹中添加文件
\[atguigu@hadoop102 files\]$ echo hello \>\> file1.txt
\[atguigu@hadoop102 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.t
xt"}
{"inode":2496275,"pos":12,"file":"/opt/module/flume/files/file2.t
xt"}
注: Linux 中储存文件元数据的区域就叫做 inode ,每个 inode 都有一个号码,操作系统
用 inode 号码来识别不同的文件, Unix/Linux 系统内部不使用文件名,而使用 inode 号码来
识别文件。
**第** **3** **章** **Flume** **进阶**
**3.1 Flume** **事务**
Flume 事务
Web
Server
Source
Sink
Eventn
HDFS
Agent
数据输入端
Flume 流式处理
数据输出端
Channel
Event2
Event1
...
接收事件
推送事件
转发事件
doPut
putList
Transaction
doCommit
doRollback
batch data
takeList
doCommit
doTake
batch data
doRollback
Transaction
•doPut: 将批数据先写入临时缓冲区 putList
Put 事务流程
•doCommit: 检查 channel 内存队列是否足够合并。
•doRollback:channel 内存队列空间不足,回滚数据
Take 事务
•doTake: 将数据取到临时缓冲区 takeList ,并将数据发送到 HDFS
•doCommit: 如果数据全部发送成功,则清除临时缓冲区 takeList
•doRollback: 数据发送过程中如果出现异常, rollback 将临时缓冲区 t
akeList 中的数据归还给 channel 内存队列。
拉取事件
**---------------------------------------------------------------------------------------**
**3.2 Flume Agent** **内部原理**
Flume Agent 内部原理
Source
Channel
Processor
Channel
Selector
Interceptor
Interceptor
Interceptor
Channel1
Channel2
Channel3
SinkProcessor
Sink1
Sink2
Sink3
1 接收数据
2 处理事件
3 将事件传递给拦截器链
4 将每个事件给 Channel 选择器
5 返回写入事件 Channel 列表
6 根据 Channel 选择
器的选择结果,将事
件写入相应 Channel 。
7 SinkProcessor 有三种:
DefaultSinkProcessor 、
LoadBalancingSinkProcessor 、
FailoverSinkProcessor
每种都有其各自的功能
Channel Selectors 有
两 种 类 型 :Replicating
Channel Selector (default) 和
Multiplexing
Channel
Selector 。 Replicating 会 将
source 过来的 events 发往所
有 channel, 而 Multiplexing 可
以配置发往哪些 Channel 。
**重要组件:**
**1)ChannelSelector**
ChannelSelector 的作用就是选出 Event 将要被发往哪个 Channel。其共有两种类型,
分别是 Replicating (复制)和 Multiplexing (多路复用)。
ReplicatingSelector 会将同一个 Event 发往所有的 Channel,Multiplexing 会根据相
应的原则,将不同的 Event 发往不同的 Channel。
**2)SinkProcessor**
SinkProcessor
共 有 三 种 类 型 , 分 别 是
DefaultSinkProcessor 、
LoadBalancingSinkProcessor 和 FailoverSinkProcessor
DefaultSinkProcessor 对 应 的 是 单 个 的 Sink , LoadBalancingSinkProcessor 和
FailoverSinkProcessor 对应的是 Sink Group,LoadBalancingSinkProcessor 可以实现负
载均衡的功能,FailoverSinkProcessor 可以错误恢复的功能。
**---------------------------------------------------------------------------------------**
**3.3 Flume** **拓扑结构**
**3.3.1** **简单串联**
图 Flume Agent 连接
这种模式是将多个 flume 顺序连接起来了,从最初的 source 开始到最终 sink 传送的
目的存储系统。此模式不建议桥接过多的 flume 数量, flume 数量过多不仅会影响传输速
率,而且一旦传输过程中某个节点 flume 宕机,会影响整个传输系统。
**3.3.2** **复制和多路复用**
图 单 source,多 channel、sink
Flume 支持将事件流向一个或者多个目的地。这种模式可以将相同数据复制到多个
channel 中,或者将不同数据分发到不同的 channel 中,sink 可以选择传送到不同的目的
地。
**---------------------------------------------------------------------------------------**
**3.3.3** **负载均衡和故障转移**
图 Flume 负载均衡或故障转移
Flume支持使用将多个sink逻辑上分到一个sink组,sink组配合不同的SinkProcessor
可以实现负载均衡和错误恢复的功能。
**3.3.4** **聚合**
图 Flume Agent 聚合
这种模式是我们最常见的,也非常实用,日常 web 应用通常分布在上百个服务器,大者
甚至上千个、上万个服务器。产生的日志,处理起来也非常麻烦。用 flume 的这种组合方式
能很好的解决这一问题,每台服务器部署一个 flume 采集日志,传送到一个集中收集日志的
**---------------------------------------------------------------------------------------**
flume,再由此 flume 上传到 hdfs、hive、hbase 等,进行日志分析。
**3.4 Flume** **企业开发案例**
**3.4.1** **复制和多路复用**
**1)案例需求**
使用 Flume-1 监控文件变动,Flume-1 将变动内容传递给 Flume-2,Flume-2 负责存储
到 HDFS。同时 Flume-1 将变动内容传递给 Flume-3,Flume-3 负责输出到 Local
FileSystem。
**2)需求分析:**
单数据源多出口案例(选择器)
Hive 日志文件
/opt/module/hive/logs
/ hive.log
Flume-file-flume 监控文件
HDFS
Hive 实时更新日志
Exec Source
Avro Sink1
Memory Channel1
Memory Channel2
flume-flume-hdfs
Avro Source
HDFS Sink
Memory Channel
flume-flume-dir
Avro Source File_roll Sink
Memory Channel
Avro Sink2
本地目录:
/opt/module/datas/flume3
Flume-1
Flume-2
Flume-3
Replicating ChannelSelector
**3)实现步骤:**
(1)准备工作
在/opt/module/flume/job 目录下创建 group1 文件夹
\[atguigu@hadoop102 job\]$ cd group1/
在/opt/module/datas/目录下创建 flume3 文件夹
\[atguigu@hadoop102 datas\]$ mkdir flume3
(2)创建 flume-file-flume.conf
配置 1 个接收日志文件的 source 和两个 channel、两个 sink,分别输送给 flume-flume
hdfs 和 flume-flume-dir。
编辑配置文件
\[atguigu@hadoop102 group1\]$ vim flume-file-flume.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 = hadoop102
a1.sinks.k1.port = 4141
a1.sinks.k2.type = avro
a1.sinks.k2.hostname = hadoop102
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)创建 flume-flume-hdfs.conf
配置上级 Flume 输出的 Source,输出是到 HDFS 的 Sink。
编辑配置文件
\[atguigu@hadoop102 group1\]$ vim flume-flume-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 = hadoop102
a2.sources.r1.port = 4141
# Describe the sink
a2.sinks.k1.type = hdfs
a2.sinks.k1.hdfs.path = hdfs:// hadoop102:9820 /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 = 30
# 设置每个文件的滚动大小大概是 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)创建 flume-flume-dir.conf
配置上级 Flume 输出的 Source,输出是到本地目录的 Sink。
编辑配置文件
\[atguigu@hadoop102 group1\]$ vim flume-flume-dir.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 = hadoop102
a3.sources.r1.port = 4142
# Describe the sink
a3.sinks.k1.type = file_roll
a3.sinks.k1.sink.directory = /opt/module/data/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
**提示** :输出的本地目录必须是已经存在的目录,如果该目录不存在,并不会创建新的目
录。
(5)执行配置文件
分别启动对应的 flume 进程:flume-flume-dir,flume-flume-hdfs,flume-file-flume。
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a3 --conf-file job/group1/flume-flume-dir.conf
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a2 --conf-file job/group1/flume-flume-hdfs.conf
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a1 --conf-file job/group1/flume-file-flume.conf
(6)启动 Hadoop 和 Hive
\[atguigu@hadoop102 hadoop-2.7.2\]$ sbin/start-dfs.sh
\[atguigu@hadoop103 hadoop-2.7.2\]$ sbin/start-yarn.sh
\[atguigu@hadoop102 hive\]$ bin/hive
hive (default)\>
(7)检查 HDFS 上数据
(8)检查/opt/module/datas/flume3 目录中数据
\[atguigu@hadoop102 flume3\]$ ll
总用量 8
-rw-rw-r--. 1 atguigu atguigu 5942 5 月 22 00:09 1526918887550-3
**3.4.2** **负载均衡和故障转移**
**1)案例需求**
使用 Flume1 监控一个端口,其 sink 组中的 sink 分别对接 Flume2 和 Flume3,采用
FailoverSinkProcessor,实现故障转移的功能。
**2)需求分析**
**---------------------------------------------------------------------------------------**
故障转移案例
Hello
Atguigu
Hive
flume-file-flume 监控文件
控
制
台
nc localhost 44444
netcat Source
Avro Sink1
Memory Channel
flume-flume-console1
Avro Source logger Sink
Memory Channel
flume-flume-console2
Avro Source logger Sink
Memory Channel
Avro Sink2
Flume-1
Flume-2
Flume-3
FailoverSinkProcessor
**3)实现步骤**
(1)准备工作
在/opt/module/flume/job 目录下创建 group2 文件夹
\[atguigu@hadoop102 job\]$ cd group2/
(2)创建 flume-netcat-flume.conf
配置 1 个 netcat source 和 1 个 channel、1 个 sink group(2 个 sink),分别输送给
flume-flume-console1 和 flume-flume-console2。
编辑配置文件
\[atguigu@hadoop102 group2\]$ vim flume-netcat-flume.conf
添加如下内容
# Name the components on this agent
a1.sources = r1
a1.channels = c1
a1.sinkgroups = g1
a1.sinks = k1 k2
# Describe/configure the source
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444
a1.sinkgroups.g1.processor.type = failover
a1.sinkgroups.g1.processor.priority.k1 = 5
a1.sinkgroups.g1.processor.priority.k2 = 10
a1.sinkgroups.g1.processor.maxpenalty = 10000
# 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 = hadoop102
a1.sinks.k2.port = 4142
# 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.sinkgroups.g1.sinks = k1 k2
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c1
(3)创建 flume-flume-console1.conf
配置上级 Flume 输出的 Source,输出是到本地控制台。
编辑配置文件
\[atguigu@hadoop102 group2\]$ vim flume-flume-console1.conf
添加如下内容
# Name the components on this agent
a2.sources = r1
a2.sinks = k1
a2.channels = c1
# Describe/configure the source
a2.sources.r1.type = avro
a2.sources.r1.bind = hadoop102
a2.sources.r1.port = 4141
# Describe the sink
a2.sinks.k1.type = logger
# 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)创建 flume-flume-console2.conf
配置上级 Flume 输出的 Source,输出是到本地控制台。
编辑配置文件
\[atguigu@hadoop102 group2\]$ vim flume-flume-console2.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 = hadoop102
a3.sources.r1.port = 4142
# Describe the sink
a3.sinks.k1.type = logger
# 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
(5)执行配置文件
分别开启对应配置文件:flume-flume-console2,flume-flume-console1,flume
netcat-flume。
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a3 --conf-file job/group2/flume-flume-console2.conf -
Dflume.root.logger=INFO,console
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a2 --conf-file job/group2/flume-flume-console1.conf -
Dflume.root.logger=INFO,console
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a1 --conf-file job/group2/flume-netcat-flume.conf
(6)使用 netcat 工具向本机的 44444 端口发送内容
$ nc localhost 44444
(7)查看 Flume2 及 Flume3 的控制台打印日志
(8)将 Flume2 kill,观察 Flume3 的控制台打印情况。
**注:使用 jps -ml 查看 Flume 进程。**
**3.4.3** **聚合**
**1)案例需求:**
hadoop102 上的 Flume-1 监控文件/opt/module/group.log,
hadoop103 上的 Flume-2 监控某一个端口的数据流,
Flume-1 与 Flume-2 将数据发送给 hadoop104 上的 Flume-3,Flume-3 将最终数据打印
到控制台。
**2)需求分析**
**---------------------------------------------------------------------------------------**
多数据源汇总案例
日志文件
/opt/module/ group.log
Flume1 配置文件
控制台
实时更新日志
Exec Source
Avro Sink
Memory Channel
Flume3 配置文件
Avro Source logger Sink
Memory Channel
主机 44444 端口
Flume2 配置文件
Netcat Source
Avro Sink
Memory Channel
通过 telnet 向 44444 端
口发送数据
Flume-1
Flume-2
Flume-3
**3)实现步骤:**
(1)准备工作
分发 Flume
\[atguigu@hadoop102 module\]$ xsync flume
在 hadoop102、hadoop103 以及 hadoop104 的/opt/module/flume/job 目录下创建一个
group3 文件夹。
\[atguigu@hadoop102 job\]$ mkdir group3
\[atguigu@hadoop103 job\]$ mkdir group3
\[atguigu@hadoop104 job\]$ mkdir group3
(2)创建 flume1-logger-flume.conf
配置 Source 用于监控 hive.log 文件,配置 Sink 输出数据到下一级 Flume。
在 hadoop102 上编辑配置文件
\[atguigu@hadoop102 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/group.log
a1.sources.r1.shell = /bin/bash -c
# Describe the sink
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = hadoop104
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:
在 hadoop103 上编辑配置文件
\[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 = hadoop103
a2.sources.r1.port = 44444
# Describe the sink
a2.sinks.k1.type = avro
a2.sinks.k1.hostname = hadoop104
a2.sinks.k1.port = 41414
# 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 到控制
台。
在 hadoop104 上编辑配置文件
\[atguigu@hadoop104 group3\]$ touch flume3-flume-logger.conf
\[atguigu@hadoop104 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 = hadoop104
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@hadoop104 flume\]$ bin/flume-ng agent --conf conf/ --name
a3 --conf-file job/group3/flume3-flume-logger.conf -
Dflume.root.logger=INFO,console
\[atguigu@hadoop102 flume\]$ bin/flume-ng agent --conf conf/ --name
a2 --conf-file job/group3/flume1-logger-flume.conf
\[atguigu@hadoop103 flume\]$ bin/flume-ng agent --conf conf/ --name
a1 --conf-file job/group3/flume2-netcat-flume.conf
(6)在 hadoop103 上向/opt/module 目录下的 group.log 追加内容
\[atguigu@hadoop103 module\]$ echo 'hello' \> group.log
(7)在 hadoop102 上向 44444 端口发送数据
\[atguigu@hadoop102 flume\]$ telnet hadoop102 44444
(8)检查 hadoop104 上数据
**3.5** **自定义** **Interceptor**
**1)案例需求**
使用 Flume 采集服务器本地日志,需要按照日志类型的不同,将不同种类的日志发往不
同的分析系统。
**2)需求分析**
在实际的开发中,一台服务器产生的日志类型可能有很多种,不同类型的日志可能需要
发送到不同的分析系统。此时会用到 Flume 拓扑结构中的 Multiplexing 结构,Multiplexing
的原理是,根据 event 中 Header 的某个 key 的值,将不同的 event 发送到不同的 Channe
**---------------------------------------------------------------------------------------**
中,所以我们需要自定义一个 Interceptor,为不同类型的 event 的 Header 中的 key 赋予
不同的值。
在该案例中,我们以端口数据模拟日志,以是否包含"atguigu"模拟不同类型的日志,
我们需要自定义 interceptor 区分数据中是否包含"atguigu",将其分别发往不同的分析
系统(Channel)。
Interceptor 和 Multiplexing ChannelSelector 案例
atguigu
flume
控
制
台
控制台实时输入数据
netcat Source
Avro Sink1
Memory Channel
flume-flume-console1
Avro Source logger Sink
Memory Channel
flume-flume-console2
Avro Source logger Sink
Memory Channel
Avro Sink2
Flume-1
Flume-2
Flume-3
控
制
台
atguigu
flume
Memory Channel
Multiplexing Channel Selector
**3)实现步骤**
(1)创建一个 maven 项目,并引入以下依赖。
\