您的位置:首页 > 大数据 > Hadoop

flume--03-flume读取web应用某个文件夹下日志到hdfs

2017-09-07 13:14 591 查看

简介

这里主要是做这个实验遇到的问题以及解决方法

问题:java.lang.OutOfMemoryError: GC overhead limit exceeded

1.准备工作

我本来想用已经写过的一个项目,那个项目是springboot写的,里面有log4j轮转日志,把日志写到一个文件夹里,我想的是flume把这些日志读取到hdfs上和hbase中,但是部署错误,因此我想个方法,本地建立一个文件夹,手动往里面放一些有格式的数据文件。

文件内容如下

字段

| hotel  |         |         |
| h_id   | id  |
|        | h_region  | 旅馆行政区划  |
|        | h_hname  | 旅馆名称    |
|        | h_address  | 旅馆地址    |
|        | h_uname  | 姓名      |
|        | h_code  | 证件号码    |
|        | h_start  | 开房时间    |
|        | h_end  | 退房时间    |
|        | h_start  | 开房时间时间戳    |
|        | h_end  | 退房时间时间戳    |
|        | h_homecode | 入住房号    |

数据样式

1,2,宾馆642,杭州市下城区xx484路373号,姓名65,U104,2006/06/23 00:00:00,2006/06/23 00:03:00,1150992000000,1150992180000,495
2,8,宾馆29,杭州市余杭区xx866路927号,姓名64,U193,2006/06/24 00:00:00,2006/06/24 00:16:00,1151078400000,1151079360000,376
3,8,宾馆190,杭州市余杭区xx81路801号,姓名56,U149,2006/06/24 00:00:00,2006/06/24 00:10:00,1151078400000,1151079000000,67
4,8,宾馆771,杭州市余杭区xx570路341号,姓名60,U870,2006/06/25 00:00:00,2006/06/25 00:06:00,1151164800000,1151165160000,761
5,1,宾馆584,杭州市上城区xx177路847号,姓名13,U552,2006/06/26 00:00:00,2006/06/26 00:09:00,1151251200000,1151251740000,583
6,5,宾馆375,杭州市西湖区xx532路372号,姓名93,U362,2006/06/27 00:00:00,2006/06/27 00:01:00,1151337600000,1151337660000,470
7,0,宾馆853,杭州市其他区xx390路777号,姓名65,U818,2006/06/28 00:00:00,2006/06/28 00:13:00,1151424000000,1151424780000,687
8,6,宾馆181,杭州市滨江区xx861路709号,姓名59,U625,2006/06/29 00:00:00,2006/06/29 00:00:00,1151510400000,1151510400000,573
9,2,宾馆813,杭州市下城区xx959路867号,姓名74,U431,2006/06/29 00:00:00,2006/06/29 00:07:00,1151510400000,1151510820000,58
10,2,宾馆771,杭州市下城区xx371路967号,姓名47,U410,2006/06/30 00:00:00,2006/06/30 00:01:00,1151596800000,1151596860000,268
11,2,宾馆803,杭州市下城区xx62路969号,姓名27,U182,2006/07/01 00:00:00,2006/07/01 00:04:00,1151683200000,1151683440000,141
12,7,宾馆838,杭州市萧山区xx418路194号,姓名2,U984,2006/07/01 00:00:00,2006/07/01 00:19:00,1151683200000,1151684340000,684
13,7,宾馆596,杭州市萧山区xx669路289号,姓名80,U819,2006/07/02 00:00:00,2006/07/02 00:19:00,1151769600000,1151770740000,305
14,3,宾馆110,杭州市拱墅区xx544路718号,姓名82,U955,2006/07/02 00:00:00,2006/07/02 00:06:00,1151769600000,1151769960000,1


在本地建立文件夹

/opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive

2.测试读取文件到hdfs上

编写flume的配置文件

vim spool_dir_hdfs.conf

#设置客户端是agent1
#source的名称是lcc_local_txt_source1,通道(缓冲器)名称lcc_memory_channel,sink的名称为lcc_sink1
agent1.sources = lcc_local_txt_source1
agent1.channels = lcc_memory_channel
agent1.sinks = lcc_sink1

###################设置source数据源#################################
agent1.sources.lcc_local_txt_source1.type = spooldir
agent1.sources.lcc_local_txt_source1.channels = lcc_memory_channel
agent1.sources.lcc_local_txt_source1.spoolDir = /opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive
agent1.sources.lcc_local_txt_source1.fileHeader = true

###################设置channel的属性#################################
agent1.channels.lcc_memory_channel.type = memory
agent1.channels.lcc_memory_channel.capacity = 100000
agent1.channels.lcc_memory_channel.transactionCapacity = 100000
agent1.channels.lcc_memory_channel.keep-alive = 30

###################设置sink要输出到哪里#################################
# Define a logger sink that simply logs all events it receives
# and connect it to the other end of the same channel.
agent1.sinks.lcc_sink1.channel = lcc_memory_channel
agent1.sinks.lcc_sink1.type = hdfs
agent1.sinks.lcc_sink1.hdfs.path = hdfs://192.168.10.173:8020/flumeTest
agent1.sinks.lcc_sink1.hdfs.writeFormat = Text
agent1.sinks.lcc_sink1.hdfs.fileType = DataStream
agent1.sinks.lcc_sink1.hdfs.rollInterval = 0
agent1.sinks.lcc_sink1.hdfs.rollSize = 1000000
agent1.sinks.lcc_sink1.hdfs.rollCount = 0
agent1.sinks.lcc_sink1.hdfs.batchSize = 1000
agent1.sinks.lcc_sink1.hdfs.txnEventMax = 1000
agent1.sinks.lcc_sink1.hdfs.callTimeout = 60000
agent1.sinks.lcc_sink1.hdfs.appendTimeout = 60000

然后运行
[root@biluos conf]#  ../bin/flume-ng agent --conf conf --conf-file spool_dir_hdfs.conf  --name agent1 -Dflume.root.logger=INFO,console

提示错误如下
17/09/<
1844b
span class="hljs-number">07 12:47:57 ERROR source.SpoolDirectorySource: FATAL: Spool Directory source lcc_local_txt_source1: { spoolDir: /opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive }: Uncaught exception in SpoolDirectorySource thread. Restart or reconfigure Flume to continue processing.
17/09/07 12:47:58 ERROR hdfs.HDFSEventSink: process failed
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.String.toCharArray(String.java:2899)
at java.util.zip.ZipCoder.getBytes(ZipCoder.java:78)
at java.util.zip.ZipFile.getEntry(ZipFile.java:310)
com.google.common.collect.MapMakerInternalMap.createSegment(MapMakerInternalMap.java:1937)
at com.google.common.collect.MapMakerInternalMap.<init>(MapMakerInternalMap.java:260)
at com.google.common.collect.MapMaker.makeCustomMap(MapMaker.java:602)
at com.google.common.collect.Interners$CustomInterner.<init>(Interners.java:59)

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:745)
Exception in thread "SinkRunner-PollingRunner-DefaultSinkProcessor" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.String.toCharArray(String.java:2899)
at java.util.zip.ZipCoder.getBytes(ZipCoder.java:78)
at java.util.zip.ZipFile.getEntry(ZipFile.java:310)
at com.google.common.collect.MapMakerInternalMap.createSegment(MapMakerInternalMap.java:1937)
at com.google.common.collect.MapMakerInternalMap.<init>(MapMakerInternalMap.java:260)
at com.google.common.collect.MapMaker.makeCustomMap(MapMaker.java:602)
at com.google.common.collect.Interners$CustomInterner.<init>(Interners.java:59
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:745)


3.java.lang.OutOfMemoryError: GC overhead limit exceeded解决方法

解决办法:
<1>ps -aux|grep flume 查看刚才启动的flume进程,发现如下信息

/usr/jdk/bin/java -Xmx20m -Dflume.root.logger=INFO -cp conf
1
<2>于是看一个flume-ng的python脚本,发现

JAVA_OPTS="-Xmx20m"
1
问题就是出在这里了,然后我把flume-ng脚本里的这个值调大后,一切运行正常了。
vim ../bin/flume-ng

JAVA_OPTS="-Xmx2048m"


重新启动就不报错了

4。新问题:

我拖过去/opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive这个文件夹放入一个133M的文件,发现集群中很多文件http://192.168.10.173:50070/explorer.html#/flumeTest 这个目录下生成的

Permission  Owner   Group   Size    Last Modified   Replication Block Size  Name
-rw-r--r--  root    supergroup  106 B   2017/9/4 上午10:48:59 1   128 MB  FlumeData.1504493223881
-rw-r--r--  root    supergroup  232 B   2017/9/4 下午12:51:08 1   128 MB  FlumeData.1504493358928
-rw-r--r--  root    supergroup  126 B   2017/9/4 下午1:57:14  1   128 MB  FlumeData.1504504621247
-rw-r--r--  root    supergroup  126 B   2017/9/4 下午2:08:45  1   128 MB  FlumeData.1504505309265
-rw-r--r--  root    supergroup  126 B   2017/9/7 上午11:50:26 1   128 MB  FlumeData.1504755927154
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571012
-rw-r--r--  root    supergroup  1.08 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571013
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571014
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571015
-rw-r--r--  root    supergroup  1.08 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571016
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571017
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:14 1   128 MB  FlumeData.1504756571018
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:15 1   128 MB  FlumeData.1504756571019
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:15 1   128 MB  FlumeData.1504756571020
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:15 1   128 MB  FlumeData.1504756571021
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:15 1   128 MB  FlumeData.1504756571022
-rw-r--r--  root    supergroup  1.08 KB 2017/9/7 上午11:56:16 1   128 MB  FlumeData.1504756571023
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:16 1   128 MB  FlumeData.1504756571024
-rw-r--r--  root    supergroup  1.08 KB 2017/9/7 上午11:56:16 1   128 MB  FlumeData.1504756571025
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:16 1   128 MB  FlumeData.1504756571026
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:16 1   128 MB  FlumeData.1504756571027
-rw-r--r--  root    supergroup  1.07 KB 2017/9/7 上午11:56:16 1   128 MB  FlumeData.1504756571028


关键是这些文件非常多,里面只有9条数据,太少了,浪费空间

5.修改配置文件

#设置客户端是agent1
###source的名称是lcc_local_txt_source1,通道(缓冲器)名称lcc_memory_channel,sink的名称为lcc_sink1
agent1.sources = lcc_local_txt_source1
agent1.channels = lcc_memory_channel
agent1.sinks = lcc_sink1

#####################设置source数据源#################################
agent1.sources.lcc_local_txt_source1.type = spooldir
agent1.sources.lcc_local_txt_source1.channels = lcc_memory_channel
agent1.sources.lcc_local_txt_source1.spoolDir = /opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive
agent1.sources.lcc_local_txt_source1.fileHeader = true

#####################设置channel的属性#################################
agent1.channels.lcc_memory_channel.type = memory
agent1.channels.lcc_memory_channel.capacity = 100000
agent1.channels.lcc_memory_channel.transactionCapacity = 100000
agent1.channels.lcc_memory_channel.keep-alive = 30

#####################设置sink要输出到哪里#################################
### Define a logger sink that simply logs all events it receives

agent1.sinks.lcc_sink1.channel = lcc_memory_channel
agent1.sinks.lcc_sink1.type = hdfs
#指定前缀 需要打开这个useLocalTimeStamp = true
agent1.sinks.lcc_sink1.hdfs.filePrefix = events-%{host}-%y-%m-%d
agent1.sinks.lcc_sink1.hdfs.path = hdfs://192.168.10.173:8020/flumeTest
agent1.sinks.lcc_sink1.hdfs.useLocalTimeStamp = true
agent1.sinks.lcc_sink1.hdfs.minBlockReplicas=1
agent1.sinks.lcc_sink1.hdfs.rollInterval=60
agent1.sinks.lcc_sink1.hdfs.rollSize=0
agent1.sinks.lcc_sink1.hdfs.rollCount=0
agent1.sinks.lcc_sink1.hdfs.idleTimeout=0


这里注意使用这些%{host}-%y-%m-%d需要打开这个useLocalTimeStamp = true,不然会报错

java.lang.NullPointerException: Expected timestamp in the Flume event headers, but it was null


原因:

sink是hdfs,然后使用目录自动生成功能。出现如题的错误,看官网文档说的是需要在每个文件记录行的开头需要有时间戳,但是时间戳的格式可能比较难调节,所以亦可设置hdfs.useLocalTimeStamp这个参数,比如以每个小时作为一个文件夹,那么配置应该是这样:

a1.sinks.k1.hdfs.path = hdfs://ubuntu:9000/flume/events/%y-%m-%d/%H
a1.sinks.k1.hdfs.filePrefix = events-
a1.sinks.k1.hdfs.round = true
a1.sinks.k1.hdfs.roundValue = 1
a1.sinks.k1.hdfs.roundUnit = hour
a1.sinks.k1.hdfs.useLocalTimeStamp = true


使用新的配置文件,发现能正常生成一个你多大的文件,就生成多大文件的hdfs上传文件

-rw-r--r--  root    supergroup  153 MB  2017/9/7 下午3:25:19  1   128 MB  events--17-09-07.1504769055418


然后我用WinSCP工具往/opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive这个目录下拖拽新文件,模拟日志论滚过程,发现报错

17/09/07 15:18:43 INFO hdfs.HDFSSequenceFile: writeFormat = Writable, UseRawLocalFileSystem = false
17/09/07 15:18:43 INFO hdfs.BucketWriter: Creating hdfs://192.168.10.173:8020/flumeTest/events--17-09-07.1504768723253.tmp
17/09/07 15:18:43 ERROR source.SpoolDirectorySource: FATAL: Spool Directory source lcc_local_txt_source1: { spoolDir: /opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive }: Uncaught exception in SpoolDirectorySource thread. Restart or reconfigure Flume to continue processing.
java.nio.charset.MalformedInputException: Input length = 2
at java.nio.charset.CoderResult.throwException(CoderResult.java:281)


问题分析:

上传没出现问题,可就是agent老是会挂掉,报这个异常。

网上解决:

然后让我重启agent才会把Spooling Directory Source所监控的目录下面的文件抽取到HDFS上去,感觉很莫名,网上搜索了一下这个错误的原因,很多都是说可能传输的文件字符集的原因,不以为然,因为我反复测试了一下,如果是字符集的原因,那么为什么我重启一下agent又可以成功的抽取数据了。

于是我想了想是不是由于同时读写导致的问题,因为我SCP文件过去,文件较大,需要一定的时间,而flume监测到有文件马上就开始逐行读取文件转化成EVENT发送到HDFS上去,这中间肯定存在同时读写一个文件了,然后就产生的这个异常问题?

目前仅仅是猜测,于是我修改了Spooling Directory Source的配置,加了这么一个配置:

tier1.sources.source1.ignorePattern = ^(.)*\.tmp$

就是忽略监控目录下面的.tmp文件。然后我修改了scp的逻辑,拷贝到另一台主机上时,先命名为:原文件名.tmp(由于是.tmp文件,agent不会采集此类文件),等SCP执行成功之后,在mv这个.tmp文件,去掉.tmp后缀,这样agent又会抽取这个文件的数据了,通过这么一处理,就巧妙的避免了同时读写一个文件的问题。

脚本调整好之后,重新运行脚本,惊喜的发现成功了,这次agent没有挂掉,大功告成了。

我的任然报错,我测试了一下,原来我上传文件的时候,临时文件的后缀名不是tmp是filepart

新的配置文件如下

#设置客户端是agent1
###source的名称是lcc_local_txt_source1,通道(缓冲器)名称lcc_memory_channel,sink的名称为lcc_sink1
agent1.sources = lcc_local_txt_source1
agent1.channels = lcc_memory_channel
agent1.sinks = lcc_sink1

#####################设置source数据源#################################
agent1.sources.lcc_local_txt_source1.type = spooldir
agent1.sources.lcc_local_txt_source1.channels = lcc_memory_channel
agent1.sources.lcc_local_txt_source1.spoolDir = /opt/moudles/01_all_test_data/02_flume_dir_to_hdfs_and_hbase_and_hive
agent1.sources.lcc_local_txt_source1.fileHeader = true
agent1.sources.lcc_local_txt_source1.ignorePattern = ^(.)*\\.filepart$

#####################设置channel的属性#################################
agent1.channels.lcc_memory_channel.type = memory
agent1.channels.lcc_memory_channel.capacity = 100000
agent1.channels.lcc_memory_channel.transactionCapacity = 100000
agent1.channels.lcc_memory_channel.keep-alive = 30

#####################设置sink要输出到哪里#################################
### Define a logger sink that simply logs all events it receives

agent1.sinks.lcc_sink1.channel = lcc_memory_channel
agent1.sinks.lcc_sink1.type = hdfs
#指定前缀 需要打开这个useLocalTimeStamp = true
agent1.sinks.lcc_sink1.hdfs.filePrefix = events-%{host}-%y-%m-%d
agent1.sinks.lcc_sink1.hdfs.path = hdfs://192.168.10.173:8020/flumeTest
agent1.sinks.lcc_sink1.hdfs.useLocalTimeStamp = true
agent1.sinks.lcc_sink1.hdfs.minBlockReplicas=1
agent1.sinks.lcc_sink1.hdfs.rollInterval=60
agent1.sinks.lcc_sink1.hdfs.rollSize=0
agent1.sinks.lcc_sink1.hdfs.rollCount=0
agent1.sinks.lcc_sink1.hdfs.idleTimeout=0


然后重新运行就不报错误了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: