flume也分为两个版本, 0.9和1.x
1.x更为灵活, 而且更为轻便.
1.x版本之后, flume成为了一个更加纯粹的数据收集和传输工具
安装
使用flume的二进制安装
解压缩后配置环境变量即可
说明
- 生产环境中往往会监控文件目录, 第1段代码的source正是文件目录
但是之后的代码都监控指定文件, 因为文件内容的更新更为方便 - 第2段代码的sink是hdfs, 其余代码的sink大多是logger
- flume代理层之间传递数据时, 对应source和sink的类型都是avro. 但是, avro sink并不是传递了avro格式的文件, 而只是使用了avro RPC进行通信
- flume的帮助
flume help
简洁明了, 值得一看.
flume提交任务的shell语句如下
flume-ng agent --conf-file time.log --name a1 -Dflume.root.logger=INFO,console
# --conf-file 可以简写为-f, 任务文件的位置
# --name 任务名
# -Dflume.root.logger=INFO,console 控制台上的日志文件显示详细信息
配置文件序号 | 内容 |
---|---|
1 | 监控文件夹并输出到控制台 |
2 | 监控文件并输出到hdfs, 配置了时间拦截器 |
3 | 扇出到日志和代理层 |
4 | 配置代理层 |
5 | sink组(代理配置和故障转移 ) |
监控文件夹并输出到控制台
a1.sinks = k1
a1.sources = r1
a1.channels = c1
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /root/flume/spooldir
a1.sinks.k1.type = logger
# 习惯性将channel相关的属性放到最后
a1.channels.c1.type = memory
# 设置通道可容纳的事务总量, ,默认100
a1.channels.c1.capacity = 1000
# 每次从source获取, 或刷入sink的事务量, 默认100
a1.channels.c1.transactionCapacity = 100
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
监控文件并输出到hdfs
flume支持使用%Y
, %m
等引用各种时间元素, 但是需要设置时间戳拦截器
相应的, flume也可以使用%{host}来引用主机名, 同样需要设置主机拦截器
a1.sinks = k1
a1.sources = r1
a1.channels = c1
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /root/flume.txt
# 设置时间拦截器
a1.sources.r1.interceptors = x1
a1.sources.r1.interceptors.x1.type = timestamp
a1.sinks.k1.type=hdfs
# 设置存储到hdfs上以分为单位的目录
a1.sinks.k1.hdfs.path=hdfs://cdh1:8020/flume/time/m=%M
# 设置生成文件的最大等待时间, 以秒为单位, 默认30, 0为不设置
a1.sinks.k1.hdfs.rollInterval = 0
# 设置生成文件的最大文件容量, 以bytes为单位, 默认1024
a1.sinks.k1.hdfs.rollSize = 0
# 设置生成文件的最大事件数量, 默认是10
a1.sinks.k1.hdfs.rollCount = 1
### 只要符合以上三个条件之一, 就生成一个文件
# 设置刷新到hdfs上所需的事件数量, 默认是100
a1.sinks.k1.hdfs.batchSize = 1
a1.sinks.k1.hdfs.fileType = DataStream
a1.channels.c1.type = memory
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
扇出到日志和代理层
扇出
简而言之, 扇出就是一个source流向多个sink
具体来说, 需要在一个任务中设置多个sink, 也对应设置多个通道
借助扇出, 我们还可以实现近实时的索引
一个sink将数据入库, 另一个sink分析数据形成索引
代理层
第一层的flume事件可以传递到下一层的flume
示例中, 第一层flume的配置, 位于{ “hostname”:“cdh1”, “ip”:“192.168.91.11” }的服务器上
a1.sources = r1
a1.sinks = k1 k2
a1.channels = c1 c2
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /root/flume.txt
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = cdh2
a1.sinks.k1.port = 19218
a1.sinks.k2.type=logger
a1.sources.r1.channels = c1 c2
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c2
a1.channels.c1.type = memory
a1.channels.c2.type = memory
配置代理层
以下示例配置文件位于{ “hostname”:“cdh2”, “ip”:“192.168.91.12” }的服务器上
为了运行sink组策略, 也应该在{ “hostname”:“cdh2”, “ip”:“192.168.91.12” }的服务器上对应配置文件
代理层的配置不受上层flume策略的影响
也就是说, 代理层只需要在source中设置监听自己的端口. 无论上层是扇出, 或是哪一种的sink组策略, 或是上层策略在不断改变, 代理层的配置都不需要改变
具体来说, 此文章中的例子都可以使用一样的代理层配置, cdh2设置好就不需要改了
a1.sinks = k1
a1.sources = r1
a1.channels = c1
a1.sources.r1.type = avro
# 特别需要注意的是, 这里监听的是自己
a1.sources.r1.bind = cdh2
a1.sources.r1.port = 19218
a1.sinks.k1.type = logger
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
sink组
flume如何防止数据丢失
- source输出和channel输入是一个事务; channel输出和sink输入也是一个事务, 只有sink确认完成输入后, channel才会将数据删除
这个特性导致flume可能收集到重复的数据(sink完成输入, 但在确认完成之前宕机, 事务失败. flume重启之后会重新输入到sink, 因而产生重复数据).在处理flume收集到的文件时需要注意去重. - 可以选择配置flume的sink组, 以实现负载均衡或者故障转移
负载均衡和故障转移是两个不同的策略. 负载均衡会尽量随机的将数据(不重复的)传递给sink组的成员, 故障转移只会传递数据给组中优先级最高的成员, 直到该成员响应超时.
如果优先级最高的成员重新连接, 数据会转而传递给该成员
对比sink组和扇出
他们都需要双sink, sink组需要额外设置sinkgroups
(示例中, 扇出使用了双channel, 原因是官网的示例中使用了双channel, 但不清楚这是否是必须的)
##### 负载均衡 #####
a1.sources = r1
a1.sinks = k1 k2
a1.sinkgroups = g1
a1.channels = c1
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /root/flume/flume.txt
a1.sources.r1.channels = c1
# 不同点在这里
a1.sinkgroups.g1.sinks = k1 k2
a1.sinkgroups.g1.processor.type = load_balance
a1.sinkgroups.g1.processor.backoff = true
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = cdh2
a1.sinks.k1.port = 19218
a1.sinks.k2.type = avro
a1.sinks.k2.hostname = cdh3
a1.sinks.k2.port = 19218
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c1
##### 故障转移 #####
a1.sources = r1
a1.sinks = k1 k2
a1.sinkgroups = g1
a1.channels = c1
a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /root/flume/flume.txt
a1.sources.r1.channels = c1
# 故障转移需要指定代理层的优先级
a1.sinkgroups.g1.sinks = k1 k2
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 = 10
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = cdh2
a1.sinks.k1.port = 19218
a1.sinks.k2.type = avro
a1.sinks.k2.hostname = cdh3
a1.sinks.k2.port = 19218
a1.channels.c1.type = memory
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c1