为了账号安全,请及时绑定邮箱和手机立即绑定

Flume案例:采集目录中文件并上传到HDFS

标签:
大数据 Hadoop

在『Flume之HelloWorld的基础上』,本例完成采集目录中的文件,并将文件上传到HDFS中。

需求

采集目录中已有的文件,并存储到HDFS中。

分析

  • 根据需求,采集目录中已有的文件,可使用Spooling Directory Source
  • 由于需要存储到HDFS,需使用HDFS Sink
  • Channel可使用基于内存的或者基于文件的,本例使用基于文件的,保证数据不丢失。
    故最终组件选择如下图所示:

image

环境

本例各组件版本如下:

  • JDK:1.8.0_202
  • Hadoop:3.2.2
  • Flume:1.9.0

配置

下面针对每一个组件进行说明和配置:

Spooling Directory Source

该source监控指定文件夹中的新文件,并在新文件出现时,从新文件中解析数据出来。当新文件被完全读入channel后,默认情况下会重命名文件,以表示文件读取已经完成。也可以配置读取完成后立刻删除;或者配置trackerDir参数,通过tracker_dir目录,来跟踪已经处理完成的文件。

本例中,source部分的配置如下:

# Describe/configure the source
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /root/jtest/flume/biz/input-file

File Channel

该Channel有两个较为重要的配置项:checkpointDirdataDirs

  • checkpointDir用于存储检查点(checkpoint)文件,默认为*~/.flume/file-channel/checkpoint*
  • dataDirs用于指定采集的数据目录,默认为*~/.flume/file-channel/data*,在不同磁盘中使用多个目录可以提高file channel的性能

默认情况下,上面两个参数的路径均在用户home目录中。那么如果在agent中有多个file channel实例,只有一个file channel可以将目录lock,另一个file channel初始化将会失败。所以最好显示指定每一个channel的检查点目录和数据目录。
本例中,channel部分的配置如下:

# Use a channel which buffers events in memory
a1.channels.c1.type = file
a1.channels.c1.checkpointDir = /root/jtest/flume/biz/file-checkpoint
a1.channels.c1.dataDirs = /root/jtest/flume/biz/file-data

HDFS Sink

这个Sink将events写入到分布式文件系统HDFS中,目前支持创建文本文件(text files)以及Sequence files,这两种文件类型均支持压缩。写入HDFS中的文件,可根据时间、文件大小、event数量进行分割(关闭当前文件,同时新建文件)。使用HDFS Sink需要安装hadoop,flume使用hadoop中的jar包与HDFS集群进行通信。

本例中,sink部分的配置如下:

# Describe the sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://bukp1:9000/flume/biz
a1.sinks.k1.hdfs.filePrefix = biz-
# 此处使用DataStream便于查看数据
a1.sinks.k1.hdfs.fileType = DataStream
a1.sinks.k1.hdfs.writeFormat = Text
# 以下指定文件分割策略,一小时或者文件大小达到128M
a1.sinks.k1.hdfs.rollInterval = 3600
a1.sinks.k1.hdfs.rollSize = 134217728
a1.sinks.k1.hdfs.rollCount = 0

其中:

  • hdfs.path:文件件在HDFS中的存储路径;
  • hdfs.filePrefix:指定文件存储在HDFS中,添加的文件前缀;
  • hdfs.fileTypehdfs.writeFormat指定文件类型和写入格式,本例中为了方便数据查看,分别设置为DataStreamText则将以文本文件形式存储数据;
  • hdfs.rollIntervalhdfs.rollSizehdfs.rollCount用于指定文件分割策略,当参数都有配置的情况下,最先符合的策略则先执行。在本例中,每一小时(rollInterval=3600)或文件大小达到128M(rollSize=134217728)时,将会进行文件分割。

完整配置

本例的完整配置如下:

# file-to-hdfs.conf: 

# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir = /root/jtest/flume/biz/input-file

# Use a channel which buffers events in memory
a1.channels.c1.type = file
a1.channels.c1.checkpointDir = /root/jtest/flume/biz/file-checkpoint
a1.channels.c1.dataDirs = /root/jtest/flume/biz/file-data

# Describe the sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://bukp1:9000/flume/bizDir
a1.sinks.k1.hdfs.filePrefix = biz-
# 此处使用DataStream便于查看数据
a1.sinks.k1.hdfs.fileType = DataStream
a1.sinks.k1.hdfs.writeFormat = Text
# 以下指定文件分割策略,一小时或者文件大小达到128M
a1.sinks.k1.hdfs.rollInterval = 3600
a1.sinks.k1.hdfs.rollSize = 134217728
a1.sinks.k1.hdfs.rollCount = 0

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

启动

分别启动HDFS集群和Flume进程。

注意:由于需操作HDFS集群,所以Flume进程节点亦需要成为hadoop的客户端节点。成为客户端节点很简单,只需要把集群中hadoop整个目录拷贝到Flume节点即可。

启动Flume:

# bin/flume-ng agent --conf conf --conf-file conf/file-to-hdfs.conf --name a1 -Dflume.root.logger=INFO,console

部分控制台输出如下:

--- 此处省略若干行 ---
2022-01-20 17:17:59,236 (conf-file-poller-0) [INFO - org.apache.flume.node.Application.startAllComponents(Application.java:207)] Starting Source r1
2022-01-20 17:17:59,237 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.source.SpoolDirectorySource.start(SpoolDirectorySource.java:85)] SpoolDirectorySource source starting with directory: /root/jtest/flume/biz/input-file
2022-01-20 17:17:59,245 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.register(MonitoredCounterGroup.java:119)] Monitored counter group for type: SOURCE, name: r1: Successfully registered new MBean.
2022-01-20 17:17:59,245 (lifecycleSupervisor-1-0) [INFO - org.apache.flume.instrumentation.MonitoredCounterGroup.start(MonitoredCounterGroup.java:95)] Component type: SOURCE, name: r1 started

由此可以看到,Source已经开始对目录*/root/jtest/flume/biz/input-file*进行监控。

have a try

接下来,我们将做若干尝试,并且修改一些配置项,观察不同的效果:

在被监控目录中,放入新文件

在/root/jtest/flume/biz/input-file目录中,放入如下图所示的文本文件:

image

出错!guava包冲突

但是,出现了如下错误:

2022-01-20 17:48:14,565 (SinkRunner-PollingRunner-DefaultSinkProcessor) [ERROR - org.apache.flume.sink.hdfs.HDFSEventSink.process(HDFSEventSink.java:459)] process failed
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
	at org.apache.hadoop.conf.Configuration.set(Configuration.java:1357)
	at org.apache.hadoop.conf.Configuration.set(Configuration.java:1338)
	at org.apache.hadoop.conf.Configuration.setBoolean(Configuration.java:1679)
	at org.apache.flume.sink.hdfs.BucketWriter.open(BucketWriter.java:221)
	at org.apache.flume.sink.hdfs.BucketWriter.append(BucketWriter.java:572)
	at org.apache.flume.sink.hdfs.HDFSEventSink.process(HDFSEventSink.java:412)
	at org.apache.flume.sink.DefaultSinkProcessor.process(DefaultSinkProcessor.java:67)
	at org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:145)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "SinkRunner-PollingRunner-DefaultSinkProcessor" java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
	at org.apache.hadoop.conf.Configuration.set(Configuration.java:1357)
	at org.apache.hadoop.conf.Configuration.set(Configuration.java:1338)
	at org.apache.hadoop.conf.Configuration.setBoolean(Configuration.java:1679)
	at org.apache.flume.sink.hdfs.BucketWriter.open(BucketWriter.java:221)
	at org.apache.flume.sink.hdfs.BucketWriter.append(BucketWriter.java:572)
	at org.apache.flume.sink.hdfs.HDFSEventSink.process(HDFSEventSink.java:412)
	at org.apache.flume.sink.DefaultSinkProcessor.process(DefaultSinkProcessor.java:67)
	at org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:145)
	at java.lang.Thread.run(Thread.java:748)

该错误原因,是因为guava版本冲突导致,在hadoop中使用的版本为guava-27.0:

hadoop-3.2.2/share/hadoop/common/lib/guava-27.0-jre.jar

而Flume中,使用的版本为guava-11.0.2:

flume-1.9.0/lib/guava-11.0.2.jar

解决办法为:删除掉flume中的guava包,并重启Flume,重启后观察控制台输出:

2022-01-20 17:58:49,275 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.hdfs.HDFSDataStream.configure(HDFSDataStream.java:57)] Serializer = TEXT, UseRawLocalFileSystem = false
2022-01-20 17:58:49,362 (SinkRunner-PollingRunner-DefaultSinkProcessor) [INFO - org.apache.flume.sink.hdfs.BucketWriter.open(BucketWriter.java:246)] Creating hdfs://bukp1:9000/flume/bizDir/biz-.1642672729275.tmp
2022-01-20 17:59:18,798 (Log-BackgroundWorker-c1) [INFO - org.apache.flume.channel.file.EventQueueBackingStoreFile.beginCheckpoint(EventQueueBackingStoreFile.java:230)] Start checkpoint for /root/jtest/flume/biz/file-checkpoint/checkpoint, elements to sync = 30
2022-01-20 17:59:18,802 (Log-BackgroundWorker-c1) [INFO - org.apache.flume.channel.file.EventQueueBackingStoreFile.checkpoint(EventQueueBackingStoreFile.java:255)] Updating checkpoint metadata: logWriteOrderID: 1642672728850, queueSize: 0, queueHead: 28
2022-01-20 17:59:18,805 (Log-BackgroundWorker-c1) [INFO - org.apache.flume.channel.file.Log.writeCheckpoint(Log.java:1065)] Updated checkpoint for file: /root/jtest/flume/biz/file-data/log-2 position: 1266 logWriteOrderID: 1642672728850

查看运行效果

可以看到,Flume已经读取了文件内容,并写入到HDFS。查看HDFS中文件:

[root@bukp4 input-file]# hdfs dfs -ls /flume/bizDir
Found 1 items
-rw-r--r--   2 root supergroup       3870 2022-01-20 17:58 /flume/bizDir/biz-.1642672729275.tmp

可以看到,HDFS相应目录中已存在文件biz-.1642672729275.tmp,并且前缀即为先前的配置项hdfs.filePrefix=biz 。继续查看这个tmp文件:

[root@bukp4 input-file]# hdfs dfs -cat /flume/bizDir/biz-.1642672729275.tmp
Introduction
Overview
Apache Flume is a distributed, reliable, and available system for efficiently collecting, aggregating and moving large amounts of log data from many different sources to a centralized data store.

The use of Apache Flume is not only restricted to log data aggregation. Since data sources are customizable, Flume can be used to transport massive quantities of event data including but not limited to network traffic data, social-media-generated data, email messages and pretty much any data source possible.

--- 此处省略若干

可以看到,文件内容已经写入到HDFS文件中。

再一次拷贝一个新文件到Flume的监控目录,最终可以看到在HDFS路径中,仍然只有biz-.1642672729275.tmp这个文件,但监控目录中新文件的内容,已经被追加到HDFS中biz-.1642672729275.tmp文件尾部。

修改source配置,再看看现象

可以注意到,在被监控的目录中已经被处理完毕的文件会被加上了*.COMPLETED*后缀:

[root@bukp4 input-file]# ll
total 8
-rw-r--r--. 1 root root 3870 Jan 20 17:48 test-text-1.dat.COMPLETED
-rw-r--r--. 1 root root  747 Jan 20 18:23 test-text-2.dat.COMPLETED

这跟Spooling Directory Source的跟踪策略和删除策略有关,相应的配置项为:

  • deletePolicy
    删除策略,用于配置在什么时候删除已经处理完毕的文件。可选配置包括:neverimmediate;默认值为never,即永不删除;
  • fileSuffix
    给已处理完毕的文件,添加的文件后缀。默认值即为.COMPLETED;
  • trackingPolicy
    跟踪策略,用于配置如何跟踪文件的处理过程,与deletePolicy配合使用,并且仅当deletePolicy设置为never时才会生效。该参数可选配置包括renametracker_dir
    • rename:文件处理完毕后文件被重命名,在文件名末尾添加一个后缀,这个后缀通过fileSuffix参数指定。
    • tracker_dir:文件处理完毕后不会被重命名,但会在参数trackerDir指定的目录中生成一个空文件,文件名为原始文件名+fileSuffix
  • trackerDir
    当跟踪策略为tracker_dir时,该参数指定用于存储相关处理过程元数据的目录。默认为*.flumespool*。该参数可配置为相对路径或者绝对路径,当配置为相对路径时,则为相对于spoolDir参数所指定的目录。
    接下来,将调整上面几个参数,验证不同参数组合下的实际效果。
一、文件处理完毕后立即删除

deletePolicy设置为immediate,配置文件source部分修改如下:

# Describe/configure the source
a1.sources.r1.type = spooldir
a1.sources.r1.deletePolicy = immediate
a1.sources.r1.spoolDir = /root/jtest/flume/biz/input-file

启动后,拷贝新的文件到spoolDir中,文件自动消失了!查看HDFS,可以看到刚才的文件内容已经被写入了HDFS相应文件中。

二、trackingPolicy策略使用tracker_dir

deletePolicy设置为never ,配置文件source部分修改如下:

# Describe/configure the source
a1.sources.r1.type = spooldir
a1.sources.r1.deletePolicy = never
a1.sources.r1.spoolDir = /root/jtest/flume/biz/input-file
a1.sources.r1.trackerDir = flumespool
a1.sources.r1.trackingPolicy = tracker_dir

此处,trackerDir使用了相对路径,则会在*/root/jtest/flume/biz/input-file*中新建该目录,重新启动后可以观察到,该目录被建立:

[root@bukp4 input-file]# ll
total 12
drwxr-xr-x. 2 root root 4096 Jan 21 14:43 flumespool
-rw-r--r--. 1 root root 3870 Jan 20 17:48 test-text-1.dat.COMPLETED
-rw-r--r--. 1 root root  747 Jan 20 18:23 test-text-2.dat.COMPLETED

拷贝新文件到spoolDir中,当文件处理完后可以观察到,在flumespool目录中出现了如下文件:

[root@bukp4 flumespool]# ll
total 0
-rw-r--r--. 1 root root 0 Jan 21 15:09 test-text-3.dat.COMPLETED

spoolDir中,文件名称不会改变:

[root@bukp4 input-file]# ll
total 16
drwxr-xr-x. 2 root root 4096 Jan 21 15:09 flumespool
-rw-r--r--. 1 root root 3870 Jan 20 17:48 test-text-1.dat.COMPLETED
-rw-r--r--. 1 root root  747 Jan 20 18:23 test-text-2.dat.COMPLETED
-rw-r--r--. 1 root root 3870 Jan 21 15:07 test-text-3.dat

以上,该案例实验完毕。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消