本文环境如下:
操作系统:CentOS 7.2.1511 64位
Flume版本:1.6.0
1. 当Flume与Hadoop不在同一服务器上
当Flume与Hadoop不在同一服务器上时,又配置了写HDFS,则Flume启动时会报找不到类的错误。
需要添加Hadoop相关的包到flume的classpath配置中(或者直接拷贝到flume的lib文件夹中)。
具体需要的包,我是在maven项目中配置:
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.4</version>
</dependency>
然后把所有依赖的包(共82个),都拷贝到flume的lib中(有些包会和lib中的重复)。实际情况应该有蛮多包是没有使用的,以后有时间再精简了。
2. 写入配置了HA的HDFS中
当你的Flume需要将数据写入HDFS中,而Hadoop服务器又配置了HA,我尝试了2种配置方案。
方案1
配置其中一个namenode,并添加到host。
该方案能用,但是Hadoop的HA就起不了作用了。当你一个节点挂掉了,flume也要手动去修改配置,才能使用另外一个namenode。
方案2
直接把Hadoop的nameservices(假设为xxfs
)配置到flume的hdfs.path
属性中。
这种方案将会报以下错:
2016-08-04 13:34:55,535 (SinkRunner-PollingRunner-DefaultSinkProcessor) [ERROR - org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:160)] Unable to deliver event. Exception follows.
org.apache.flume.EventDeliveryException: java.lang.IllegalArgumentException: java.net.UnknownHostException: xxfs
at org.apache.flume.sink.hdfs.HDFSEventSink.process(HDFSEventSink.java:463)
at org.apache.flume.sink.DefaultSinkProcessor.process(DefaultSinkProcessor.java:68)
at org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:147)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: java.net.UnknownHostException: xxfs
at org.apache.hadoop.security.SecurityUtil.buildTokenService(SecurityUtil.java:374)
at org.apache.hadoop.hdfs.NameNodeProxies.createNonHAProxy(NameNodeProxies.java:310)
at org.apache.hadoop.hdfs.NameNodeProxies.createProxy(NameNodeProxies.java:176)
at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:668)
at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:604)
at org.apache.hadoop.hdfs.DistributedFileSystem.initialize(DistributedFileSystem.java:148)
at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2596)
at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:91)
at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2630)
at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2612)
at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:370)
at org.apache.hadoop.fs.Path.getFileSystem(Path.java:296)
at org.apache.flume.sink.hdfs.BucketWriter$1.call(BucketWriter.java:243)
at org.apache.flume.sink.hdfs.BucketWriter$1.call(BucketWriter.java:235)
at org.apache.flume.sink.hdfs.BucketWriter$9$1.run(BucketWriter.java:679)
at org.apache.flume.auth.SimpleAuthenticator.execute(SimpleAuthenticator.java:50)
at org.apache.flume.sink.hdfs.BucketWriter$9.call(BucketWriter.java:676)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
... 1 more
Caused by: java.net.UnknownHostException: xxfs
... 21 more
最终的方案
(1)将Hadoop的nameservices(假设为xxfs
)配置到flume的hdfs.path
属性中。例如:
a1.sinks.userSink.hdfs.path = hdfs://xxfs/flume
(2)将Hadoop服务器上配置好的core-site.xml、hdfs-site.xml拷贝到flume的conf文件夹下。
再重新启动Flume将可以用了。
(3)将Hadoop所使用的几台服务器做好host。
3. Kafka Channel的parseAsFlumeEvent
由于项目有需求要把Flume中的部分数据写Kafka,而我做过测试,通过Memory Channel+Kafka Sink的性能不如直接使用Kafka Channel,以上为背景。
实际使用的过程中,发现parseAsFlumeEvent这个配置起不了作用。也就是无论parseAsFlumeEvent配置为true还是false,都会转为Flume Event。
这样的话,造成的结果是,会始终都把Flume的headers中的信息混合着内容一起写入Kafka的消息中,这显然不是我所需要的,我只是需要把内容写入即可。
后来我查询了一些资料,网络上也有人发现了这个bug,并且提交bugfix给Flume官方,但是要下一个版本(1.7)才能解决。
无奈之下,只能先采用Memory Channel+Kafka Sink的方式作为代替了。