Flume: 数据采集机制

1.什么是flume

  • 无论数据来自什么企业,或是多大量级,通过部署Flume,可以确保数据都安全、及 时地到达大数据平台,用户可以将精力集中在如何洞悉数据上。
Flume的定义
  • Flume由Cloudera公司开发,是一个分布式、高可靠、高可用的海量日志采集、聚合、传输的系统。
  • Flume支持在日志系统中定制各类数据发送方,用于采集数据;
  • Flume提供对数据进行简单处理,并写到各种数据接收方的能力。
  • 简单的说,Flume是实时采集日志的数据采集引擎。

Flume有3个重要组件:
  • Source
  • Channel
  • Sink
特点:
  • 分布式:flume分布式集群部署,扩展性好
  • 可靠性好: 当节点出现故障时,日志能够被传送到其他节点上而不会丢失
  • 易用性:flume配置使用较繁琐,对使用人员专业技术要求高
  • 实时采集:flume采集流模式进行数据实时采集
适用场景:
  • 适用于日志文件实时采集
其他数据采集工具
  • dataX:阿里开源软件异构数据源离线同步工具,没有界面,以执行脚本方式运行
  • Xkettle:开源ETL工具,有可视化设计器进行可视化操作,使用简单
  • Logstash:应用程序日志、事件的传输、处理、管理和搜索的平台。可以用它来统 一对应用程序日志进行收集管理,提供了Web接口用于查询和统计。
  • Scribe:Facebook开源的日志收集系统,它能够从各种日志源上收集日志,存储到 一个中央存储系统(可以是NFS,分布式文件系统等)上,以便于进行集中统计分析处理。
  • sqoop:待更新

2. Flume体系结构

虚线内是一个agent,本质是一个JVM

内部组件: source、channel、sink
  • Flume架构中的组件:
Agent:
  • -- 本质上是一个 JVM 进程,该JVM进程控制Event数据流从外部日志生产者 那里传输到目的地(或者是下一个Agent)。
  • 一个完整的Agent中包含了三个组 件Source、Channel和Sink,Source是指数据的来源和方式,Channel是一个数 据的缓冲池,Sink定义了数据输出的方式和目的地。
Source:
  • --是负责接收数据到Flume Agent的组件。
  • Source组件可以处理各种类 型、各种格式的日志数据,包括avro、exec、spooldir、netcat等。、
Channel:
  • -- 是位于Source和Sink之间的缓冲区。
source内存肯定是有限的,大批量数据压进去,需要一个缓冲区
  • Channel允许Source和Sink运作 在不同的速率上
  • Channel是线程安全的可以同时处理多个Source的写入操作 及多个Sink的读取操作
  • 常用的Channel包括:
-- Memory Channel 
Memory Channel是内存中的队列。Memory Channel在允许数据丢失的情景下适用。
如果不允许数据丢失,应该避免使用Memory Channel,
因为程序死亡、机器宕机或者重启都可能会导致数据丢失;

--File Channel
File Channel将所有事件写到磁盘。
因此在程序关闭或机器宕机的情况下不会丢失数据

-- kafka Channel:见kafka部分
Sink
  • 不断从channel 中获取数据,发送到目的地
-- 不断地轮询Channel中的事件且批量地移除它们,
并将这些事件批量写入到 存储或索引系统、或者被发送到另一个Flume Agent。 
  • -- Sink是完全事务性的
在从Channel批量删除数据之前,每个Sink用Channel启 动一个事务。
批量事件一旦成功写出到存储系统或下一个Flume Agent,Sink就 利用Channel提交事务。
  • -- 事务一旦被提交,该Channel从自己的内部缓冲区删除事件。
Event:
  • 是Flume定义的一个数据流传输的小单位。

3. Flume拓扑结构

3.1 串行模式

  • 将多个flume给顺序连接起来,从初的source开始到终sink传送的目的存储系统
  • 此模式不建议桥接过多的flume数量, flume数量过多不仅会影响传输速率,而且一 旦传输过程中某个节点flume宕机,会影响整个传输系统。

3.2 复制模式(单Souce多Channel、Sink模式)

  • 将事件流向一个或者多个目的地。这种模式将数据源复制到多个channel中,每个 channel都有相同的数据,sink可以选择传送的不同的目的地。

3.3 负载均衡模式(单Source、Channel多Sink)

  • 将多个sink逻辑上分到一个sink组,flume将数据发送到不同的sink,主要解决负载 均衡和故障转移问题。
第一个失败了就往第二个发

3.4 聚合模式

  • 这种模式常见的,也非常实用,日常web应用通常分布在上百个服务器,大者甚至 上千个、上万个服务器。产生的日志,处理起来也非常麻烦。用这种组合方式能很好 的解决这一问题,每台服务器部署一个flume采集日志,传送到一个集中收集日志的 flume,再由此flume上传到hdfs、hive、hbase、消息队列中。

最后以一个flume聚合,再放入HDFS

4. Flume内部原理

总体数据流向:Souce => Channel => Sink
  • Channel: 处理器、拦截器、选择器

图中编号为执行顺序。红色即为channel处理的内部流程,channel可能不止一个,sink也可能不止1个

具体过程
  • Source接收事件,交给其Channel处理器处理事件
  • 处理器通过拦截器Interceptor
拦截器不止一个,可能是多个串联,对事件一些处理,比如压缩解码,正则拦截,时 间戳拦截,分类等
  • 经过拦截器处理过的事件再传给Channel选择器,将事件写入相应的Channel。
  • Channel Selector选择器有两种
  1. Replicating Channel Selector复制(默认)
会将source过来的Event发往所有 Channel(比较常用的场景是,用多个Channel实现冗余副本,保证可用性) 

2. Multiplexing Channel Selector选择

根据配置分发event。
此selector会根据 event中某个header对应的value来将event发往不同的channel 
  • 最后由Sink处理器处理各个Channel的事件

5. 基础应用

  • Flume 支持的数据源种类有很多,可以来自directory、http、kafka等。Flume提供 了Source组件用来采集数据源。
  • 日志采集就是根据业务需求选择合适的Source、Channel、Sink,并将其组合在一起

5.1 常见的 Source

avro source:

--监听 Avro 端口来接收外部 avro 客户端的事件流。avro-source 接收到的是经过avro序列化后的数据,然后反序列化数据继续传输。如果是avro source的话,源数据必须是经过avro序列化后的数据。利用 Avro source可以实现多 级流动、扇出流、扇入流等效果。接收通过flume提供的avro客户端发送的日 志信 息。

exec source:

-- 可以将命令产生的输出作为source。如ping 192.168.234.163、tail -f hive.log。

netcat source

-- 一个NetCat Source用来监听一个指定端口,并接收监听到的 数据。

spooling directory source:

---将指定的文件加入到“自动搜集”目录中。flume会 持续监听这个目录,把文件当做source来处理。注意:一旦文件被放到目录中后, 便不能修改,如果修改,flume会报错。此外,也不能有重名的文件。

Taildir Source:

--监控指定的多个文件,一旦文件内有新写入的数据, 就会将其写入到指定的sink内,本来源可靠性高,不会丢失数据。其不会对于跟踪的 文件有任何处理,不会重命名也不会删除,不会做任何修改。目前不支持Windows 系统,不支持读取二进制文件,支持一行一行的读取文本文件。

5.2 Channel组件:缓存数据

  • 采集到的日志需要进行缓存,Flume提供了Channel组件用来缓存数据。常见的 Channel 有:

(1)memory channel:缓存到内存中(常用)

(2)file channel:缓存到文件中

(3)JDBC channel:通过JDBC缓存到关系型数据库中

(4)kafka channel:缓存到kafka中

5.3 Sink组件

  • 缓存的数据终需要进行保存,Flume提供了Sink组件用来保存数据。常见的 Sink 有

(1)logger sink:将信息显示在标准输出上,主要用于测试

(2)avro sink:Flume events发送到sink,转换为Avro events,并发送到配置好 的hostname/port。从配置好的channel按照配置好的批量大小批量获取events

(3)null sink:将接收到events全部丢弃

(4)HDFS sink:将 events 写进HDFS。支持创建文本和序列文件,支持两种文件 类型压缩。文件可以基于数据的经过时间、大小、事件的数量周期性地滚动

(5)Hive sink:该sink streams 将包含分割文本或者JSON数据的events直接传送 到Hive表或分区中。使用Hive 事务写events。当一系列events提交到Hive时,它们 马上可以被Hive查询到

(6)HBase sink:保存到HBase中

(7)kafka sink:保存到kafka中

日志采集就是根据业务需求选择合适的Source、Channel、Sink,并将其组合在一起

6. 入门案例

  • 中文flume帮助文档: Flume 1.9用户手册中文版
  • 业务需求:监听本机 8888 端口,Flume将监听的数据实时显示在控制台

6.1 需求分析:

  • 使用 telnet 工具可以向 8888 端口发送数据
  • 监听端口数据,选择 netcat source
(5.1中的netcat source:) 
  • channel 选择 memory 数据实时显示,选择 logger sink

6.2 实现步骤:

  • 1.安装 telnet 工具
yum install telnet1
  • 2. 检查 8888 端口是否被占用。如果该端口被占用,可以选择使用其他端口完成任务
lsof -i:8888

一开始发现有占用,先把这个进程关掉,重新检查,发现没有被占用了,被占用就用kill把占用这个端口的进程杀了

  • 3. 创建 Flume Agent 配置文件。 flume-netcat-logger.conf
通过查阅文档,找到设置参数,没有默认值(缺省值)的一定要进行设置

-- 具体参数设置看前面6.1的需求分析,选择source channel sin类型,配置端口号

找到netcat,没有默认值的必须要在配置中写出,有默认值的可以缺省

# a1是agent的名称。source、channel、sink的名称分别为:r1  c1  k1 
a1.sources = r1 
a1.channels = c1 
a1.sinks = k1

# source 
a1.sources.r1.type = netcat     # type组件类型,这次选用netcat型的source
a1.sources.r1.bind = 192.168.10.103   # bind: 要监听的主机名hostname或IP地址
a1.sources.r1.port = 8888      # port: 监听的端口号:根据需求要监听8888端口 

# channel 
a1.channels.c1.type = memory     # type组件类型,这次选用memory型的channel
a1.channels.c1.capacity = 10000    #capacity:内存中存储Event的最大数,默认值100太小,手动设置为10000
a1.channels.c1.transactionCapacity = 100   #  transactionCapacity source或者sink 每个事务中存取 Event的操作数量(不能比capacity大)

# sink 
a1.sinks.k1.type = logger       # type组件类型,这次选用logger 型的sink
 
# source、channel、sink之间的关系 
a1.sources.r1.channels = c1   #sources.r1 的 channel 是 c1
a1.sinks.k1.channel = c1      #sink k1 的 channel 是 c1
  • 如果没跑通,把注释删掉,仔细检查配置文件是否粘贴对了

-- Memory Channel 是使用内存缓冲Event的Channel实现。速度比较快速,容量会受到 jvm 内存大小的限制,可靠性不够高适用于允许丢失数据,但对性能要求较高 的日志采集业务。

  • 4. 启动Flume Agent
$FLUME_HOME/bin/flume-ng agent --name a1 \              
--conf-file $FLUME_HOME/conf/flume-netcat-logger.conf \ 
-Dflume.root.logger=INFO,console

-- 写成一行
flume-ng agent --name a1 --conf-file flume-netcat-logger.conf -Dflume.root.logger=INFO,console
  • 命令解释
* 反斜杠表示一行命令还没输完,告诉命令行先不要执行,另起一行输命令
1. flume-ng 说明是新一代的flume引擎
2. agent --name a1:  表示 name。定义agent的名字,要与参数文件一致 
3. conf-file。指定参数文件位置 
4.-D表示flume运行时动态修改 flume.root.logger 参数属性值,并将控制台日志 打印级别设置为INFO级别。
6. 在屏幕上显示的日志,日志的级别是什么,日志显示在什么地方(console即命令窗口)
7. 日志级别包括:log、info、warn、error
  • 5. 使用 telnet 向本机的 8888 端口发送消息
telnet 192.168.10.103 8888
  • 6. 在 Flume 监听页面查看数据接收情况

-- 这边输入,那边更新

INFO sink.LoggerSink: Event: { headers:{} body: 68 65 6C 6C 6F 20 77 6F 72 6C 64 0D
             hello world. } 
INFO sink.LoggerSink: Event: { headers:{} body: 41 72 65 20 79 6F 75 20 6F 6B 3F 0D
             Are you ok?. }

6.3 解决没有消息

  • 1个小bug没有接到消息

00:00 / 00:07

倍速

高清

00:07

  • 配置文件写错了

不要写一行

  • 改正配置后成功运行

00:00 / 00:50

倍速

高清

00:50

7. 进阶案例

7.1 监控日志文件信息到HDFS

  • 业务需求:监控本地日志文件,收集内容实时上传到HDFS
需求分析:
  • 使用 tail -F 命令即可找到本地日志文件产生的信息 source 选择 exec。
  • exec 监听一个指定的命令,获取命令的结果作为数据源。
  • source组件从这个命令的结果中取数据。当agent进程挂掉重启后,可能存在数 据丢失;
  • channel 选择 memory
  • sink 选择 HDFS
tail -f
等同于--follow=descriptor,根据文件描述符进行追踪,
当文件改名或被删除,追踪停止

tail -F
等同于--follow=name --retry,根据文件名进行追踪,并保持重试,
即该文件被删除或改名后,如果再次创建相同的文件名,会继续追踪
实现步骤
  • 环境准备
Flume要想将数据输出到HDFS,必须持有Hadoop相关jar包。
将
commons-configuration-1.6.jar 
hadoop-auth-2.9.2.jar 
hadoop-common2.9.2.jar 
hadoop-hdfs-2.9.2.jar commons-io-2.4.jar 
htrace-core4-4.1.0-incubating.jar
-- 拷贝到 $FLUME_HOME/lib 文件夹下
  • 拷贝文件
# 在
$HADOOP_HOME/share/hadoop/httpfs/tomcat/webapps/webhdfs/WEBINF/lib 有这些文件
cd
$HADOOP_HOME/share/hadoop/httpfs/tomcat/webapps/webhdfs/WEBINF/lib
-- 要是报错,就用cd 一点一点进到这个目录里,再cp
cp commons-configuration-1.6.jar $FLUME_HOME/lib/
cp hadoop-auth-2.9.2.jar $FLUME_HOME/lib/
cp hadoop-common-2.9.2.jar $FLUME_HOME/lib/
cp hadoop-hdfs-2.9.2.jar $FLUME_HOME/lib/
cp commons-io-2.4.jar $FLUME_HOME/lib/
cp htrace-core4-4.1.0-incubating.jar $FLUME_HOME/lib/
  • 创建配置文件 flume-exec-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/servers/hive-2.3.7/logs/hive.log

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

# Describe the sink
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs://192.168.10.101:9000/flume/%Y%m%d/%H%M

# 上传文件的前缀
a2.sinks.k2.hdfs.filePrefix = logs-

# 是否使用本地时间戳
a2.sinks.k2.hdfs.useLocalTimeStamp = true

# 积攒500个Event才flush到HDFS一次
a2.sinks.k2.hdfs.batchSize = 500

# 设置文件类型,支持压缩。DataStream没启用压缩
a2.sinks.k2.hdfs.fileType = DataStream

# 1分钟滚动一次
a2.sinks.k2.hdfs.rollInterval = 60
# 128M滚动一次
a2.sinks.k2.hdfs.rollSize = 134217700

# 文件的滚动与Event数量无关
a2.sinks.k2.hdfs.rollCount = 0
# 最小冗余数
a2.sinks.k2.hdfs.minBlockReplicas = 1
# Bind the source and sink to the channel
a2.sources.r2.channels = c2
a2.sinks.k2.channel = c2

注意:配置文件中两处地方特别注意
  • 1. hive.log的路径
1. hive.log的路径
hive.log 在我的虚拟机上是存在/opt/servers/hive-2.3.7/logs/hive.log下的, 所以
a2.sources.r2.command = tail -F /opt/servers/hive-2.3.7/logs/hive.log

确认好hive.log的位置

  • 2. 集群namenode 的 hdfs 端口要和 hadoop配置文件core-site的xml保持一致,否则无法连接hdfs

Diamon:hdfs无法连接. java.net.ConnectException: 拒绝连接2 赞同 · 0 评论文章​编辑

00:00 / 00:52

倍速

高清

00:52

  • 启动Agent
$FLUME_HOME/bin/flume-ng agent --name a2 \
--conf-file ~/conf/flume-exec-hdfs.conf \
-Dflume.root.logger=INFO,console



-- cd 到配置文件的目录 
cd $FLUME_HOME/conf

-- -- 在conf 目录下执行
flume-ng agent --name a2 --conf-file flume-exec-hdfs.conf -Dflume.root.logger=INFO,console
  • 启动Hadoop和Hive,操作Hive产生日志
start-dfs.sh
start-yarn.sh
# 在命令行多次执行
hive -e "show databases"

00:28 / 00:59

倍速

高清

flume上传日志

  • 查看hdfs上生成的日志文件
 hdfs dfs -ls /flume


-- 因为配置中设置了输出路径是
a2.sinks.k2.hdfs.path = hdfs://192.168.10.101:9000/flume/%Y%m%d/%H%M

7.2 监控目录采集信息到HDFS

业务需求
  • 监控指定目录,收集信息实时上传到HDFS
需求分析
  • source 选择 spooldir
spooldir 能够保证数据不丢失,且能够实现断点续传
  • channel 选择 memory
  • sink 选择 HDFS
-- spooldir Source监听一个指定的目录,
即只要向指定目录添加新的文件,source组件就可以获取到该信息,并解析该文件的内容,写入到channel。

-- sink处理完之后,标记该文件已完成处理,文件名添加 .completed 后缀。

-- 虽然是自动监控整个目录,但是只能监控文件,
如果以追加的方式向已被处理的文件中添加内容,source并不能识别。

--需要注意的是:

拷贝到spool目录下的文件不可以再打开编辑
无法监控子目录的文件夹变动
被监控文件夹每500毫秒扫描一次文件变动
适合用于同步新文件,但不适合对实时追加日志的文件进行监听并同步
实现
  • 创建配置文件。flume-spooldir-hdfs.conf
# Name the components on this agent
a3.sources = r3
a3.channels = c3
a3.sinks = k3

# Describe/configure the source
a3.sources.r3.type = spooldir
a3.sources.r3.spoolDir = /root/upload
a3.sources.r3.fileSuffix = .COMPLETED
a3.sources.r3.fileHeader = true

# 忽略以.tmp结尾的文件,不上传
a3.sources.r3.ignorePattern = ([^ ]*\.tmp)
# Use a channel which buffers events in memory
a3.channels.c3.type = memory
a3.channels.c3.capacity = 10000
a3.channels.c3.transactionCapacity = 500
# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://192.168.10.101:9000/flume/upload/%Y%m%d/%H%M

# 上传文件的前缀
a3.sinks.k3.hdfs.filePrefix = upload-
# 是否使用本地时间戳
a3.sinks.k3.hdfs.useLocalTimeStamp = true
# 积攒500个Event,flush到HDFS一次
a3.sinks.k3.hdfs.batchSize = 500
# 设置文件类型
a3.sinks.k3.hdfs.fileType = DataStream
# 60秒滚动一次
a3.sinks.k3.hdfs.rollInterval = 60
# 128M滚动一次
a3.sinks.k3.hdfs.rollSize = 134217700
# 文件滚动与event数量无关
a3.sinks.k3.hdfs.rollCount = 0
# 最小冗余数
a3.sinks.k3.hdfs.minBlockReplcaticas = 1
# Bind the source and sink to the channel
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3 
  • 启动Agent
$FLUME_HOME/bin/flume-ng agent --name a3 \
--conf-file ~/conf/flume-spooldir-hdfs.conf \
-Dflume.root.logger=INFO,console

-- cd 到配置文件的目录 
cd $FLUME_HOME/conf

-- -- 在conf 目录下执行
flume-ng agent --name a3 --conf-file flume-spooldir-hdfs.conf -Dflume.root.logger=INFO,consoleki 
  • 向upload文件夹中添加文件
cp /root/wc.txt f.log
-- 复制一份,重命名为f.log

  • 查看HDFS上的数据
hdfs dfs -ls /flume/upload

00:00 / 00:59

倍速

高清

00:59

HDFS Sink
  • 一般使用 HDFS Sink 都会采用滚动生成文件的方式,滚动生成文件的策略有:
基于时间
hdfs.rollInterval
缺省值:30,单位秒
0禁用
基于文件大小
hdfs.rollSize
缺省值:1024字节
0禁用
基于event数量
hdfs.rollCount
10
0禁用
基于文件空闲时间
hdfs.idleTimeout
缺省值:0。禁用
基于HDFS文件副本数
hdfs.minBlockReplicas
默认:与HDFS的副本数一致
要将该参数设置为1;否则HFDS文件所在块的复制会引起文件滚动
其他重要配置
hdfs.useLocalTimeStamp
使用本地时间,而不是event header的时间戳
默认值:false
hdfs.round
时间戳是否四舍五入
默认值false
如果为true,会影响所有的时间,除了t%
hdfs.roundValue
四舍五入的最高倍数(单位配置在hdfs.roundUnit),但是要小于当前时间
默认值:1
hdfs.roundUnit
可选值为:second、minute、hour
默认值:second
  • 如果要避免HDFS Sink产生小文件,参考如下参数设置:
a1.sinks.k1.type=hdfs
a1.sinks.k1.hdfs.useLocalTimeStamp=true
a1.sinks.k1.hdfs.path=hdfs://linux121:9000/flume/events/%Y/%m/
%d/%H/%M
a1.sinks.k1.hdfs.minBlockReplicas=1
a1.sinks.k1.hdfs.rollInterval=3600
a1.sinks.k1.hdfs.rollSize=0
a1.sinks.k1.hdfs.rollCount=0
a1.sinks.k1.hdfs.idleTimeout=0

7.3 级联Agent

  • 监控日志文件采集数据到HDFS、本地文件系统
业务需求
  • 监控日志文件,收集信息上传到HDFS 和 本地文件系统
需求分析:
  • 需要多个Agent级联实现
要有两个agent分别向 hdfs 和 本地输送日志信息 
  • source 选择 taildir
  • channel 选择 memory
  • 最终的 sink 分别选择 hdfs、file_roll
taildir Source
  • Flume 1.7.0加入的新Source,相当于 spooldir source + exec source。
  • 可以监控多个目录,并且使用正则表达式匹配该目录中的文件名进行实时收集。
  • 实时监控一批文件,并记录每个文件最新消费位置,agent进程重启后不会有 数据丢失的问题
 目前不适用于Windows系统;其不会对于跟踪的文件有任何处理,不会重命名也不
会删除,不会做任何修改。不支持读取二进制文件,支持一行一行的读取文本文件。

Agent1 的 选择器要复制信息为两份,分发给 本地和HDFS, 同时,Avro sink 发的消息,对面要用 Avro Source 接收

创建第一个配置文件: Agent1
  • Agent1包括:
1个 taildir source 
2个 memory channel
2个 avro sink 
  • flume-taildir-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

# source
a1.sources.r1.type = taildir

# 记录每个文件最新消费位置
a1.sources.r1.positionFile = /root/flume/taildir_position.json
a1.sources.r1.filegroups = f1

# 备注:.*log 是正则表达式;这里写成 *.log 是错误的
a1.sources.r1.filegroups.f1 = /opt/servers/hive-2.3.7/logs/.*log

# sink
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = 192.168.10.103
a1.sinks.k1.port = 9091

a1.sinks.k2.type = avro
a1.sinks.k2.hostname = 192.168.10.103
a1.sinks.k2.port = 9092

# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 10000
a1.channels.c1.transactionCapacity = 500

a1.channels.c2.type = memory
a1.channels.c2.capacity = 10000
a1.channels.c2.transactionCapacity = 500


# Bind the source and sink to the channel
a1.sources.r1.channels = c1 c2
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c2
创建第二个配置文件:Agent2
  • Agent2 传数据给hdfs
1个 avro source
1个 memory channel
1个 hdfs sink
  • flume-avro-hdfs.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 = 192.168.10.103
a2.sources.r1.port = 9091

# Describe the channel
a2.channels.c1.type = memory
a2.channels.c1.capacity = 10000
a2.channels.c1.transactionCapacity = 500
# Describe the sink
a2.sinks.k1.type = hdfs
a2.sinks.k1.hdfs.path = hdfs://192.168.10.103:9000/flume2/%Y%m%d/%H

# 上传文件的前缀
a2.sinks.k1.hdfs.filePrefix = flume2-

# 是否使用本地时间戳
a2.sinks.k1.hdfs.useLocalTimeStamp = true
# 500个Event才flush到HDFS一次
a2.sinks.k1.hdfs.batchSize = 500

# 设置文件类型,可支持压缩
a2.sinks.k1.hdfs.fileType = DataStream

# 60秒生成一个新的文件
a2.sinks.k1.hdfs.rollInterval = 60
a2.sinks.k1.hdfs.rollSize = 0
a2.sinks.k1.hdfs.rollCount = 0
a2.sinks.k1.hdfs.minBlockReplicas = 1

# Bind the source and sink to the channel
a2.sources.r1.channels = c1
a2.sinks.k1.channel = c1
创建第三个配置文件: Agent3
  • Agent3包括:
1个 avro source
1个 memory channel
1个 file_roll sink
  • flume-avro-file.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 = 192.168.10.103
a3.sources.r1.port = 9092
# Describe the sink
a3.sinks.k1.type = file_roll

# 目录需要提前创建好
a3.sinks.k1.sink.directory = /root/flume/output
# Describe the channel
a3.channels.c2.type = memory
a3.channels.c2.capacity = 10000
a3.channels.c2.transactionCapacity = 500

# Bind the source and sink to the channel
a3.sources.r1.channels = c2
a3.sinks.k1.channel = c2
启动 3个Agent
  • 先把本地的输出目录建好,不然报错
 mkdir /root/flume/output
  • 从后往前启动,3、2、1
-- cd 到配置文件的目录 
cd $FLUME_HOME/conf

-- -- 在conf 目录下执行
flume-ng agent --name a3 --conf-file flume-avro-file.conf -Dflume.root.logger=INFO,consoleki &

flume-ng agent --name a2 --conf-file flume-avro-hdfs.conf -Dflume.root.logger=INFO,consoleki &

flume-ng agent --name a1 --conf-file flume-taildir-avro.conf -Dflume.root.logger=INFO,consoleki &
  • & 的作用
& 放在命令后面表示设置此进程为后台进程

默认情况下,进程是前台进程,这时此进程(命令执行相当于本质是开启一个进程)就把Shell给占据了,我们无法进行其他操作,
对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个'&'实现这个目的。

Linux命令后面加&_shen_zhu的博客-CSDN博客_linux命令后面的&符号​blog.csdn.net/shen_zhu/article/details/80413830​编辑

执行hive命令产生日志
执行hive命令产生日志
 hive -e "show databases"
分别检查HDFS文件、本地文件、以及消费位置文件
  • 检查本地文件
cd /root/flume

输出到本地的日志文件

  • 检查hdfs的输出
hdfs dfs -ls /flume2

# 3种监控日志文件Source的对比

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

7.5 Bug:HDFS连接不上

  • 配置文件中一定要仔细比对,hdfs的地址是namenode节点的,但是flume组件的地址是flume的节点地址

8. 高级特性

8.1 拦截器

  • Flume支持在运行时对event进行修改或丢弃,通过拦截器来实现;
Flume里面的拦截器是实现了org.apache.flume.interceptor.Interceptor 接口的类;
拦截器可以根据配置 修改 甚至 丢弃 event;
Flume也支持链式的拦截器执行方式,在配置文件里面配置多个拦截器就可以了;
拦截器的顺序取决于它们配置的顺序,Event 按照顺序经过每一个拦截器;
 
时间添加戳拦截器
  • 这个拦截器会向每个event的header中添加一个时间戳属性进去
Host添加拦截器
  • 这个拦截器会把当前Agent的 hostname 或者 IP 地址写入到Event的header中
正则表达式过滤拦截器
  • 这个拦截器会把Event的body当做字符串来处理,并用配置的正则表达式来匹配。可 以配置指定被匹配到的Event丢弃还是没被匹配到的Event丢弃。

8.2 选择器

  • source可以向多个channel同时写数据,所以也就产生了以何种方式向多个channel 写的问题:
replication(复制,缺省)。数据完整地发送到每一个channel;
multiplexing(多路复用)。通过配置来按照一定的规则进行分发;  
自定义选择器
  • 自定义选择器就是开发一个 org.apache.flume.ChannelSelector 接口的实现类。实现 类以及依赖的jar包在启动时候都必须放入Flume的classpath。

8.3 Sink组逻辑处理器

  • 可以把多个sink分成一个组, Sink组逻辑处理器可以对这同一个组里的几个sink进行 负载均衡 或者 其中一个sink发生故障后将输出Event的任务转移到其他的sink上。
N个sink将Event输出到对应的N个目的地的,
通过 Sink组逻辑处理器 可以把这N个sink配置成负载均衡或者故障转移的工作方式:

-- 负载均衡是将channel里面的Event,按照配置的负载机制(比如轮询)分别发
送到sink各自对应的目的地

--故障转移是这N个sink同一时间只有一个在工作,其余的作为备用,
工作的sink,挂掉之后备用的sink顶上
 
默认
  • 默认的组逻辑处理器就是只有一个sink的情况,这种情况就没必要配置sink组了。前 面的例子都是 source - channel - sink这种一对一,单个sink的。
故障转移
  • 故障转移组逻辑处理器维护了一个发送Event失败的sink的列表,保证有一个sink是 可用的来发送Event。
故障转移机制的工作原理是将故障sink降级到一个池中,在池中为它们分配冷却期
(超时时间),在重试之前随顺序故障而增加。 Sink成功发送事件后,它将恢复到
实时池。sink具有与之相关的优先级,数值越大,优先级越高。 如果在发送Event时
Sink发生故障,会继续尝试下一个具有最高优先级的sink。

例如,在优先级为80的
sink之前激活优先级为100的sink。如果未指定优先级,则根据配置中的顺序来选取。 
负载均衡
  • 负载均衡Sink 选择器提供了在多个sink上进行负载均衡流量的功能。 它维护一个活 动sink列表的索引来实现负载的分配。 支持轮询( round_robin )【默认值】和随 机( random )两种选择机制分配负载。
工作时,此选择器使用其配置的选择机制选择下一个sink并调用它。 如果所选sink无
法正常工作,则处理器通过其配置的选择机制选择下一个可用sink。 此实现不会将
失败的Sink列入黑名单,而是继续乐观地尝试每个可用的Sink。
  
  • 如果所有sink调用都失败了,选择器会将故障抛给sink的运行器。
如果 backoff 设置为true则启用了退避机制,失败的sink会被放入黑名单,达到一定
的超时时间后会自动从黑名单移除。 如从黑名单出来后sink仍然失败,则再次进入
黑名单而且超时时间会翻倍,以避免在无响应的sink上浪费过长时间。 如果没有启
用退避机制,在禁用此功能的情况下,发生sink传输失败后,会将本次负载传给下一
个sink继续尝试,因此这种情况下是不均衡的。
 

左边是负载均衡,数据会按顺序尽可能使得每个sink都有活干,右边是故障转移,每时每刻只有1个在起作用,其他都是备份,第一个sink挂了就去找下一个

8.4 事务机制

  • 一提到事务,首先就想到的是关系型数据库中的事务,事务一个典型的特征就是将一 批操作做成原子性的,要么都成功,要么都失败。
在Flume中一共有两个事务:
  • Put事务。在Source到Channel之间
  • Take事务。Channel到Sink之间
从 Source 到 Channel 过程中,
数据在 Flume 中会被封装成 Event 对象,也就是一 批 Event ,
把这批 Event 放到一个事务中,
把这个事务也就是这批event一次性的放 入Channel 中。

同理,Take事务的时候,也是把这一批event组成的事务统一拿出来 到sink放到HDFS上。
Flume中的 Put 事务
  • 事务开始的时候会调用一个 doPut 方法, doPut 方法将一批数据放在putList 中;
putList在向 Channel 发送数据之前先检查 Channel 的容量能否放得下,
如果放不下一个都不放,只能doRollback;

数据批的大小取决于配置参数 batch size 的值;

putList的大小取决于配置 Channel 的参数 transaction capacity 的大小,该
参数大小就体现在putList上;(Channel的另一个参数 capacity 指的是 Channel 的容量);
   
  • 数据顺利的放到putList之后,接下来可以调用 doCommit 方法,把putList中所有 的 Event 放到 Channel 中,成功放完之后就清空putList;
在doCommit提交之后,事务在向 Channel 存放数据的过程中,事务容易出问题。
如 Sink取数据慢,而 Source 放数据速度快,容易造成 Channel 中数据的积压,如
果 putList 中的数据放不进去,会如何呢?

此时会调用 doRollback 方法,doRollback方法会进行两项操作:将putList清空;
抛出 ChannelException异常。source会捕捉到doRollback抛出的异常,然后source
就将刚才的一批数据重新采集,然后重新开始一个新的事务,这就是事务的回滚。 

Put 事务: 把数据放进去

Flume中的 Take 事务
  • Take事务同样也有takeList,HDFS sink配置有一个 batch size,这个参数决定 Sink 从 Channel 取数据的时候一次取多少个,所以该 batch size 得小于 takeList 的大 小,而takeList的大小取决于 transaction capacity 的大小,同样是channel 中的 参数。
Take事务流程:事务开始后:
  • doTake方法会将channel中的event剪切到takeList中。
如果后面接的是HDFS
Sink的话,在把Channel中的event剪切到takeList中的同时也往写入HDFS的IO
缓冲流中放一份event(数据写入HDFS是先写入IO缓冲流然后flush到HDFS);
  • 当takeList中存放了batch size 数量的event之后,就会调用doCommit方法, doCommit方法会做两个操作:
1. 针对HDFS Sink,手动调用IO流的flush方法,将IO流缓冲区的数据写入到
HDFS磁盘中;
2、 清空takeList中的数据
  • flush到HDFS的时候组容易出问题。
flush到HDFS的时候,可能由于网络原因超时导 致数据传输失败,
这个时候调用doRollback方法来进行回滚,回滚的时候由于 takeList 中还有备份数据,
所以将takeList中的数据原封不动地还给channel,这时候就完成了事务的回滚


但是,如果flush到HDFS的时候,数据flush了一半之后出问题了,这意味着已经有
一半的数据已经发送到HDFS上面了,现在出了问题,同样需要调用doRollback方法
来进行回滚,回滚并没有“一半”之说,它只会把整个takeList中的数据返回给
channel,然后继续进行数据的读写。这样开启下一个事务的时候容易造成数据重复
的问题。

Take 事务: 取数据

8.5 可靠性

  • Flume在数据进行采集传输的时候,有可能会造成数据的重复,但不会丢失数据。
agent 内部传输如果不成功就rollback
  • Flume在数据传输的过程中是否可靠,还需要考虑具体使用Source、Channel、Sink 的类型。
-- 分析Source
       exec Source ,后面接 tail -f ,这个数据也是有可能丢的

      TailDir Source ,这个是不会丢数据的,它可以保证数据不丢失

--- 分析sink

Hdfs Sink,数据有可能重复,但是不会丢失

-- 分析channel。
理论上说:要想数据不丢失的话,还是要用 File channel;
memory channel 在 Flume 挂掉的时候是有可能造成数据的丢失的。
 
  • 如果使用 TailDir source 和 HDFS sink,所以数据会重复但是不会丢失

9. 高可用案例——故障转移

故障转移
  • 故障转移组逻辑处理器维护了一个发送Event失败的sink的列表,保证有一个sink是可用的来发送Event。
  • 故障转移机制的工作原理是将故障sink降级到一个池中,在池中为它们分配冷却期 (超时时间),在重试之前随顺序故障而增加。 Sink成功发送事件后,它将恢复到 实时池。sink具有与之相关的优先级,数值越大,优先级越高。 如果在发送Event时 Sink发生故障,会继续尝试下一个具有高优先级的sink。 例如,在优先级为80的
  • sink之前激活优先级为100的sink。如果未指定优先级,则根据配置中的顺序来选 取。
  • 要使用故障转移选择器,不仅要设置sink组的选择器为failover,还有为每一个sink 设置一个唯一的优先级数值。 可以使用 maxpenalty 属性设置故障转移时间的上限 (毫秒)。

猜你喜欢

转载自blog.csdn.net/TangYuG/article/details/132755265