Flume avro client和hdfs sink 完成自定义目录文件收集

准备

背景: 把分散在个边缘Node的访问日志收集到中央节点,然后在做后续的处理。边缘Node(例如hostname为BJ-NODE1) 上的日志每分钟切出来一个文件,通过 Flume avro client 把5分钟粒度内的日志上传到中央节点,生成一个文件,文件名类似 BJ-NODE1_timestamp.log

大概的逻辑如下图

avro client
D中央
avro client
avro client

需要考虑的点:

  • hostname等信息怎么带到中央的Flume?
    我们可以用 flume-ng avro-clientR,--headerFile 选项,用一个带有k,v的header文件把参数信息传递到上层的Flume
  • HDFS sink支持本地文件存储吗?因为不想增加一个HDFS的维护工作

测试

下面是一个简单的测试,把一个文件通过 Flume A的 avro-client ,发送给另一个Flume B,并且根据携带的参数生成文件

清单

  • OS: Centos7 (192.168.1.210)
  • Flume1.8

FlumeB (接收端)的配置,以及启动

flume的conf目录下增加 server.conf

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

## Test
a1.sources.s1.type = avro
a1.sources.s1.bind = 192.168.1.210
a1.sources.s1.port = 44444
a1.sources.s1.channels = c1

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

a1.sinks.k1.channel = c1
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /data/logs/%{func}/%Y-%m-%d/%H/%M
a1.sinks.k1.hdfs.fileType = DataStream
a1.sinks.k1.hdfs.writeFormat=TEXT
a1.sinks.k1.hdfs.filePrefix = %{sn}_%{timestamp}
a1.sinks.k1.hdfs.fileSuffix = .log
a1.sinks.k1.hdfs.batchSize = 1000
a1.sinks.k1.hdfs.rollSize = 0
a1.sinks.k1.hdfs.rollCount = 0
a1.sinks.k1.hdfs.rollInterval = 0
a1.sinks.k1.hdfs.idleTimeout = 30
#a1.sinks.k1.hdfs.useLocalTimeStamp = true

接收端Flume监听44444端口,需要avro client传递3个参数 sn, func, timestamp (timestamp可以是client传过来,也可以在接收端生成,看最后注释的 a1.sinks.k1.hdfs.useLocalTimeStamp),生成的目录格式为 /data/logs/%{func}/%Y-%m-%d/%H/%M, 文件的前缀 %{sn}_%{timestamp}

启动参数

$ cd /opt/flume/
$ bin/flume-ng agent --conf conf --conf-file conf/server.conf --name a1 -Dflume.monitoring.type=http -Dflume.monitoring.port=44441 -Dflume.root.logger=INFO,console

FlumeA(发送端)

  • 被发送文件 update1.csgo.wmsj.cn 里面是一些访问日志
  • header文件 header.access.conf
timestamp=1554947700000
func=access
sn=BJ-NODE1
  • 发送命令
# /opt/flume/bin/flume-ng avro-client -H 192.168.1.210 -p 44444 -F update1.csgo.wmsj.cn -R header.access.conf
Warning: No configuration directory set! Use --conf  to override.
Info: Including Hive libraries found via () for Hive access
+ exec /opt/jdk/bin/java -Xmx20m -cp '/opt/flume/lib/*:/lib/*' -Djava.library.path= org.apache.flume.client.avro.AvroCLIClient -H 192.168.1.210 -p 44444 -F update1.csgo.wmsj.cn -R header.access.conf

结果

查看上传的日志

# tree /data/logs/
/data/logs/
└── access
    └── 2019-04-11
        └── 09
            └── 55
                └── BJ-NODE1_1554947700000.1554961698951.log

多次执行上面的命令结果如下

# tree /data/logs/ -lsh
/data/logs/
└── [  23]  access
    └── [  15]  2019-04-11
        └── [  15]  09
            └── [4.0K]  55
                ├── [ 22K]  BJ-NODE1_1554947700000.1554961698951.log
                └── [ 22K]  BJ-NODE1_1554947700000.1554961771992.log

说明上传的时候是上传一个文件,Flume保存一个文件,如果想要多个文件合并为一个文件呢?

修改了一个 server.conf的配置

a1.sinks.k1.hdfs.rollSize = 268435456

再次从client发送文件,连续多次发送,会合并为一个文件,但是间隔很长还是会有多个文件,具体参考文档就好,主要是下面几个参数。

Name Defalut Description Remarks
hdfs.rollInterval 30 Number of seconds to wait before rolling current file (0 = never roll based on time interval) 写入多久
hdfs.rollSize 1024 File size to trigger roll, in bytes (0: never roll based on file size) 文件大小
hdfs.rollCount 10 Number of events written to file before it rolled (0 = never roll based on number of events) 写入行数
hdfs.idleTimeout 0 Timeout after which inactive files get closed (0 = disable automatic closing of idle files) 无写入多久关闭

flume的会为一个新的参数组创建一个文件,然后等待写入,写入到一定的文件大小,或者写入多少行之后,或者写入一定时间之后,就会滚动到下一个文件,写入停止之后等待超时之后关闭文件。当文件关闭之后,如果有相同的参数组来了,还是会创建新文件。

测试了上面的几种组合,基本符合自己的理解。

总结

  • 如果在 headerFile 添加时间戳,记得是毫秒单位
  • HDFS sink不仅支持 HDFS也支持
  • 根据自己的场景来合并文件或者切割大文件

你可能感兴趣的:(自动运维)