java/python kafka thrift序列化
我们在学习kafka的时候往kafka中写数据大部分写的都是字符串,也就是`
properties.put(“key.serializer”,“org.apache.kafka.common.serialization.StringSerializer”);
properties.put(“value.serializer”,“kafka.kafkaThriftSerierlize.serializer.ThriftSerializer”);`
kafka提供了序列化和反序列化的接口支持自定义序列化。关于什么是序列化请参考thrift序列化
一. 为什么使用thrift序列化?
1.thrift是跨语言的
2.体积小节省kafka空间
1.1 理解跨语言
此时我想将java的对象存入kafka,那么怎么办,kafka的序列化不支持存储java对象?最容易的想法就是用java语言自定义序列化器(通过继承kafka的序列化器接口),和反序列化器(通过继承kafka的反序列化器接口)。
上面的做法有没有问题? 答案是可以有也可以没有,为什么这么说?如果你的生产者和消费者都用java语言那是没问题的。 但是假如consumer消费者用python语言来写的话就无法解析kafka中的数据了,
因为你的序列化反序列化器都是java语言写的。
那么你可能会问, 那么我用python代码写一个和java版本一样的反序列化器按理说不就可以了吗?小伙子想法不错, 但是依旧不行,请接着往下看。
假设我们现在用java实现了序列化和反序列化器,那么它的工作流程如下
- 生产者:调用序列化器将java对象序列化转成二进流制存入kafka,。
- 消费者:调用反序列化器将从kafka获取的二进制流转成 java 对象。 看到没,反序列化器是将二进制流转成了java对象, 那么你用python是无法定义java对象的, 那么你可能会问了,那我定义一个python对象保持和java对象结构一致不行吗? 答案是不行,因为kafka中二进制数据是基于java对象的,那也就意味着反序列化的时候也必须用java对象接收,所以python是不行。
而解决这个问题的办法就是采用第三方的支持跨语言的序列化/反序列化框架,所谓的跨语言, 意思就是说,不管你是什么语言生成的对象,那你存入kafka的时候 用我的序列化协议,我帮你序列化, 当你从kafka中获取数据的时候, 也请用我来反序列化。 这就是跨语言的序列化框架。 thrift就是其中之一。
我们以java语言做生产者, python语言作消费者来举例子,整个流程如下:
- java生产者: java对象–>thrift将java对象序列化成二进制流存入kafka
- python消费者:从kafka获取二进制流数据-> thrift将二进制流反序列化成python对象 看到没,存入kafka中的java对象,最后被解析成了python对象, thrift就是为我们做了转换,python不认识java对象没关系,thrift认识,thrift解析之后帮你生成python对象就行了。
总结:借用thrift就将python和java对象连接起来了。kafka存储的实际上不是python对象也不是java对象,而是thrift自己的数据结构,只不过thrift能将这个结构体转化成python或者是java对象同时也将java或者python转成自己的结构体。
所以thrift需要提供这个结构体用于做java和python对象的映射,这也是核心。
二.环境准备
这部分需要读者自行准备
2.1 安装kafka
2.2 建立maven项目导入kafka和thrift
此部分是java,用于生产数据借用thrift序列化之后存入kafka
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.1.0</version>
</dependency>
2.3 python环境准备
我用的是python3.7
需要安装以下两个东西:
pip install kafka-python
pip install thrift==0.13.0
python用于从kafka中接收数据,转成python对象。
三.thrift 结构体生成
我们说过,序列化反序列化其实都是操作的thrift的结构体, 而不是真正意义上的python和java对象,结构体可以帮我们做结构体到实体对象的自动映射, 所以说对应的java和python的对象不是我们自己写出来的, 而是thrift通过指定结构体 而后命令行 自动生成java或者是python对象。 所以说为了实现自动转化, java和python代码都需要这个结构体,而且必须保持一致。 先看下我的代码目录。
java中Person对象是thrift调用: thrift --gen java kafka.thrift生成的
python中contants.py和ttypes.py是thrift用: thrift --gen py kafka.thrift生成的,其中ttypes.py中就有python版本的Person对象。
而结构体就被定义在了kafka.thrift中,其内容:
typedef i16 short
typedef i32 int
typedef i64 long
typedef bool boolean
typedef string String
struct Person {
1: optional String username,
2: optional int age,
3: optional boolean married
}
/*
* 此文件用于定义序列化存入kafka topic的数据结构
*/
四. 代码部分
代码放入github仓库中:https://github.com/fish-gangan/java-thrift-kafka-python
版权归原作者 会飞的鱼干干 所有, 如有侵权,请联系我们删除。