thrift序列化协议

Posted Java夜未眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了thrift序列化协议相关的知识,希望对你有一定的参考价值。

Apache Thrift 脱胎于 Facebook ,是一种高效的、支持多种编程语言的远程服务调用的框架。它的序列化协议同样可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

使用

以Java为例子,首先需要引入对应的依赖。

<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.12.0</version>
</dependency>

官方提供了从thirft文件生成对应的实体类,实际开发中使用maven插件来进行编译期的代码生成,但是thirft的的插件并不像protobuf那样提供对应的下载,而是需要自己去下载,并且指定位置。pom文件引入对应插件。

<!-- thirft plugin -->
<plugin>
<groupId>org.apache.thrift.tools</groupId>
<artifactId>maven-thrift-plugin</artifactId>
<version>0.1.11</version>
<configuration>
<thriftExecutable>./thrift-0.12.0.exe</thriftExecutable>
<generator>java</generator>
</configuration>
<executions>
<execution>
<id>thrift-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

下面我们定义一下要使用的类,src/main/thirft 下创建一个*.thirft的文件来定义消息体

namespace java com.lihongkun.serialize

struct ThriftEntity{
1:i64 id;
2:string name;
3:string category;
4:i64 price;
5:i64 appId;
6:i64 ctr;
}

struct ThriftResponse{
1:i32 code;
2:list<ThriftEntity> data;
}

使用它编译后生成的类使用如下:

private static ThriftResponse initProtoResponse() {
List<ThriftEntity> data = new ArrayList<>();

for (long index = 0; index < DATA_SIZE; index++) {
ThriftEntity thriftEntity = new ThriftEntity();
thriftEntity.setAppId(index);
thriftEntity.setCategory(String.valueOf(index));
thriftEntity.setCtr(index);
thriftEntity.setId((int) index);
thriftEntity.setName(String.valueOf(index));
thriftEntity.setPrice(index);
data.add(thriftEntity);
}

ThriftResponse response = new ThriftResponse();
response.setCode((int) DATA_SIZE);
response.setData(data);

return response;
}

对于序列化,它并不能直接转成二进制,而是需要thirft对应的辅助类TTransport和TBinaryProtocol来进行处理:

ByteArrayOutputStream out = new ByteArrayOutputStream();
TTransport transport = new TiostreamTransport(out);
TBinaryProtocol protocol = new TBinaryProtocol(transport);

long timeWatch = System.currentTimeMillis();
for(int i=0;i<LOOP_SIZE;i++){
response.write(protocol);
}
System.out.println(System.currentTimeMillis() - timeWatch);

对比

同样从效率和存储来进行对比

效率

还是以数据大小递增,循环1万次的例子

DATA_SIZE jackson protobuf thirft
10 260 ms 156 ms 94ms
50 330 ms 219 ms 250ms
100 527 ms 296 ms 450ms
200 744 ms 437 ms 735ms
300 1109 ms 562 ms 937ms

从上述数据可看出,随着数据量的增加thrift的效率其实跟json的差距在缩小。

存储
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new FileOutputStream("thrift.txt"));
TTransport gzTransport = new TIOStreamTransport(gzipOutputStream);
TBinaryProtocol gzProtocol = new TBinaryProtocol(gzTransport);
for(int i=0;i<LOOP_SIZE;i++){
response.write(gzProtocol);
}
gzipOutputStream.flush();
gzipOutputStream.close();

生成的文件是1966 KB,介于json 和 protobuf之间 ,json 是2737 KB ,protobuf 是405 KB。

综上,thirft的存储和序列化效率比json好,但是相比于protobuf还是有一定的差距。

以上是关于thrift序列化协议的主要内容,如果未能解决你的问题,请参考以下文章

Apache Thrift系列详解 - 序列化机制

服务端(后端)| Thrift序列化的核心思想

dubbo/dubbox 增加原生thrift及avro支持

使用 Apache Thrift 时如何检测协议不匹配?

环境初始化 Build and Install the Apache Thrift IDL Compiler Install the Platform Development Tools(代码片段

RPC实践-Thrift