使用Flume-KafkaSource实时采集avro格式数据

业务描述:

最近项目中需要实时采集业务数据库CDC数据(这里数据已被序列化为avro格式数据),这里技术架构我们采用了Flume+Hdfs。

了解Flume的朋友都知道它的组件分为三部分:source,channel,sink。具体原理部分这里就不再赘述,可查看官网或flume技术博客,这里具体讲一下实现流程及添坑之路。

业务过来的数据放在在kafka里,所以source端采用的是kafkaSource,说白了就是kafkaConsumer,sink选用的是hdfsSink,channel这里选的是file type。

hdfsSink写入文件格式有两种一是:Text File,二是Sequence File,不管选用哪种文件格式落地到hdfs后都不能直接使用,前面说到了业务数据已被序列化为avro格式,但需求是hdfs上的数据必须是直接可用的。

考虑了几种解决方式:

1,使用hive创建外部表关联hdfs上的数据,这里就有问题了,虽然hive支持读取seq文件格式,但我们这里seq文件里(hdfsSink使用Sequence File格式存储)的数据是avro的格式,我试着建表查询了一下,结果是乱码,text File也一样,这种方式就pass掉了。其实hive可以直接读取avro格式数据指定数据的schema就可以了,但是。。。我这个文件格式是行不通了,它可以自己实现接口序列化数据为avro格式。

2,使用API读avro数据,这种方式首先需要使用API读取seq文件数据然后再使用avro的API反序列化,根据hadoop指南书中hadoop IO那一章节中的demo,读取了seq文件的数据,然后去翻avro官网的API,发现其官网给的demo是把数据序列化为avro文件,然后反序列化这个avro文件,和我的需求不太一样,emmm。。。继续翻API,貌似找到了一个可用的class,最后还是不成功,这个方式也pass了。

3,使用kafkaConsumer自身参数反序列化avro,这个方式我在网上翻了很多博客,大多是千篇一律与实际需求不符,有的博客说直接配置这两个参数:

“key.deserializer”, "org.apache.kafka.common.serialization.StringDeserializer"
“value.deserializer”, "org.apache.kafka.common.serialization.ByteArrayDeserializer"

首先我不知道这样数据怎么反序列化出来的,其次kafkaConsumer本身默认参数就是这两个。

正确配置如下(个人认为):

“key.deserializer”, "io.confluent.kafka.serializers.KafkaAvroDeserializer"
“value.deserializer”, "io.confluent.kafka.serializers.KafkaAvroDeserializer"
“schema.registry.url”, “http://avro-schema.user-defined.com”

这里key的反序列化方式可以根据业务那边给到的格式而定,我这里key-value都是avro格式。

看到还有给出这两个参数,大家可以根据需求加上看看,我这里没用

kafka.consumer.specific.avro.reader = true
useFlumeEventFormat = true

本以为这样就可以搞定了,但结果往往不如预期,直接报错:

解决了几个错误后最终定位到这个错误就是不能反序列的根本问题,于是查看kafkaSource源码发现类型转换有点问题(仅指此次需求), 也就是图上所说的GenericRecord转换String出错。

解决方法:挠头中。。。

flume支持自定义source,赶紧翻flume书根据书上demo写了一个source,具体实现其实就是这一行代码:

ConsumerRecords records = consumer.poll(100)

把conumer返回的record类型改一下,这样最终实现了avro反序列化数据后的json格式。但是还没完,虽然实现了功能但自己写的代码肯定没有源码写的优质,所有我就想把源码的kafkaSource拿出来改改看效果咋样,果不其然,经过一番折腾最终完美实现。整个周期用了一周左右的时间。。。实属不易。以上如有哪里错误还请大神指出改正,多谢~~

下面是所用的pom文件,注意版本注意版本注意版本,重要说三遍。因为版本不对我拿了一个旧版本的源码改半天,各种坑。confluent这个源是必须得配的,maven仓库里没有,cloudera看个人情况而定。

        
        
            org.apache.flume.flume-ng-sources
            flume-kafka-source
            1.6.0-cdh5.16.2
            ${scope.version}
        
        
            org.apache.flume
            flume-ng-core
            1.6.0-cdh5.16.2
            ${scope.version}
        
        
            io.confluent
            kafka-avro-serializer
            5.2.2
            ${scope.version}
        
 

  
        
            confluent
            Confluent
            http://packages.confluent.io/maven/
        
        
            cloudera
            https://repository.cloudera.com/artifactory/cloudera-repos/
        
    

 

你可能感兴趣的:(使用Flume-KafkaSource实时采集avro格式数据)