问题:flume指定HDFS类型的Sink时,采集数据至HDFS指定目录,会产生大量小文件。
问题重现:
1、创建flume配置文件flume-env.sh,:
flume配置文件如下(根据自身需要修改):
因为flume可以配置多种采集方式,每种采集方式对应一个agent配置文件,flume即通过运行agent完成采集工作,这里为了方便重现问题,直接监控整个目录。
flume的agent配置文件如下(根据自身需要修改):
2、建立待监控目录:
3、执行flume的agent
/mnt/disk1/apache-flume-1.7.0-bin/bin/flume-ng agent -n a1 -c /root/flume_conf_jbw -f /root/flume_agent_conf_jbw/a1.conf -Dflume.root.logger=INFO,console
a1为agent的名称
可见以采集完成的 文件会加上.COMPLETE后缀,注意,若此时再在监控目录新建同名文件,flume会报错,因为采集完成后会产生相同的文件名的文件。若发生此情况,需要重新运行flume的agent。
在HDFS目录上查看采集到的数据,内容如下,零散小文件:
解决方案:
检查flume配置文件
a1.sinks.k1.hdfs.round=true
a1.sinks.k1.hdfs.round=true
a1.sinks.k1.hdfs.round=true,
将以上三行删除,新增如下两行
a1.sinks.k1.hdfs.rollSize=0
a1.sinks.k1.hdfs.rollCount=0
再次重启Flume客户端采集即可。可见不再是小文件了,如下:
分析原因:
Flume可以设置文件
查阅flume配置参数,如下:
rollSize
默认值:1024,当临时文件达到该大小(单位:bytes)时,滚动成目标文件。如果设置成0,则表示不根据临时文件大小来滚动文件。
rollCount
默认值:10,当events数据达到该数量时候,将临时文件滚动成目标文件,如果设置成0,则表示不根据events数据来滚动文件。
round
默认值:false,是否启用时间上的”舍弃”,类似于”四舍五入”,如果启用,则会影响除了%t的其他所有时间表达式;
roundValue
默认值:1,时间上进行“舍弃”的值;
roundUnit
默认值:seconds,时间上进行”舍弃”的单位,包含:second,minute,hour
当设置了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 17:38:59时候,hdfs.path依然会被解析为:
/flume/events/20151016/17:30/00
因为设置的是舍弃10分钟内的时间,因此,该目录每10分钟新生成一个。
此时,若当时间为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
本次产生大量小文件的原因就是hdfs.path中没有指定对应的目录日期对应格式(%y-%m-%d/%H%M%S)。
解决方案:
去掉round时间系列参数,并将rollSize和rollCount置0,表示不根据临时文件大小和event数量来滚动文件(滚动文件即指将HDFS上生成的以.tmp结尾的临时文件转换为实际存储文件)。当然,也可以调大rollSize参数(如调至100000000,表示100MB滚动文件,单位是bytes)。
PS:网上还有另一种出现大量小文件对应的解决方案,即设置a1.sinks.k1.hdfs.minBlockReplicas=1。因为文件会因为所在块的复制而滚动文件。