关于thrift的一些探索——thrift序列化技术
thrift的IDL,相当于一个钥匙。而thrift传输过程,相当于从两个房间之间的传输数据。
图-1
(因为Thrift采用了C/S模型,不支持双向通信:client只能远程调用server端的RPC接口,但client端则没有RPC供server端调用,这意味着,client端能够主动与server端通信,但server端不能主动与client端通信而只能被动地对client端的请求作出应答。所以把上图-1中的箭头,画为单向箭头更为直观)基于上图,Thrift的IDL文件的作用可以描述为,从房间A要传递一批数据给房间B,把数据装在箱子里,锁上锁,然后通过Transport Channel把带锁的箱子给房间B,而Thrift IDL就是一套锁跟钥匙。房间A跟房间B都有同样的一个thrift IDL文件,有了这个文件就可以生成序列化跟反序列化的代码,就像锁跟钥匙一样。而一旦没有了Thrift IDL文件,房间A无法将数据序列化好锁紧箱子,房间B没有钥匙打开用箱子锁好传输过来的数据。因此,IDL文件的作用就在此。
一、为什么要用Thrift序列化, 不用纯文本的协议
我能想到的用thrift提供的thrift binary protocol而不用json、xml等纯文本序列化协议的几个好处如下:
- 序列化后的体积小, 省流量
- 序列化、反序列化的速度更快,提高性能
- 兼容性好,一些接口,涉及多种语言的int32、int64等等跟语言、机器、平台有关, 用纯文本可能有兼容性的问题
- 结合thrift transport技术,可以RPC精准地传递对象,而纯文本协议大多只能传递数据,而不能完完全全传递对象
关于以上几点我个人认为的好处,下面作一下简单解答
1.1 序列化后的体积小, 省流量
给出测试的IDL Services_A.thrift内容如下,定义了一些数据格式,这个结构体数据复杂度一般,有list、也有list对象、也有一些基本的struct等等。
namespace php Services.test.A
namespace java Services.tets.A
struct student{
1:required string studentName, #学生姓名
2:required string sex, #性别
3:required i64 age, #学生年龄
}
struct banji{
1:required string banjiName, #班级名称
2:required list<student> allStudents, #所有学生
}
struct school {
1:required string schoolName,
2:required i64 age,
3:required list<string> zhuanye, #所有专业
4:required list<banji> allBanji, #所有班级
}
分别把Services_A.thrift 序列化为json、跟thrift.bin文件,序列化到文件中。对比文件大小。
这里用php写了一个例子, 代码如下:
<?php
/**
* Created by PhpStorm.
* User: dengpan
* Date: 16/4/21
* Time: 12:39
*/
ini_set('memory_limit','10240M');
require_once __DIR__ . "/Thrift/ClassLoader/ThriftClassLoader.php";
use ThriftClassLoaderThriftClassLoader;
use ThriftProtocolTBinaryProtocol;
use ThriftTransportTSocket;
use ThriftTransportTFramedTransport;
use ThriftTransportTPhpStream;
use ThriftTransportTPhpStreamMy;
use ThriftTransportTBufferedTransport;
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', __DIR__);
$loader->registerNamespace('Services', __DIR__);
$loader->registerDefinition('Services', __DIR__);
$loader->register();
require "Types.php";
$school = [];
$school['schoolName'] = "hahhaha";
$school['age'] = 60;
$school['zhuanye'] = [
'专业1',
'专业2',
'专业3',
];
$nameArr = ["张三", "李四", "王五", "王菲", "张韶涵", "王祖贤", "范冰冰", "新垣结衣", "詹姆斯", "诺维茨基"];