Facebook 的 Thrift
更多内容,前往个人博客
Thrift 源于 Facebook,在 2007 年 Facebook 将 Thrift 作为一个开源项目提交给了 Apache 基金会。对于当时的 Facebook 来说,创造 Thrift 是为了解决 Facebook 各系统间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性,因此 Thrift 可以支持多种程序语言,如 C++、C#、Cocoa、Erlang、Haskell、Java、Ocami、Perl、PHP、Python、Ruby 和 Smalltalk。它被当作一个远程过程调用(RPC)框架来使用。
在多种不同的语言之间通信,Thrift 可以作为高性能的通信中间件使用,它支持数据(对象)序列化和多种类型的 RPC 服务。Thrift 适用于静态的数据交换,需要先确定好它的数据结构,当数据结构发生变化时,必须重新编辑 IDL 文件、生成代码和编译,这一点跟其他 IDL 工具相比可以视为是 Thrift 的弱项。Thrift 适用于搭建大型数据交换及存储的通用工具,对于大型系统中的内部数据传输,相对于 JSON 和 XML 在性能和传输大小上都有明显的优势。
一、Thrift 主要由5部分组成
1)、语言系统以及 IDL 编译器:负责由用户给定的 IDL 文件生成相应语言的接口代码;
2)、TProtocol:RPC 的协议层,可以选择多种不同的对象序列化方法,如 JSON 和 Binary;
3)、TTransport:RPC 的传输层,同样可以选择不同的传输层实现,如 Socket、NIO、MemoryBuffer 等;
4)、TProcessor:作为协议层和用户提供的服务实现之间的纽带,负责调用服务实现的接口;
5)、TServer:聚合TProtocol、TTransport 和 TProcessor 等对象;
我们重点关注的是编解码框架,与之对应的就是 TProtocol。由于 Thrift 的 RPC(Remote Procedure Call) 服务调用和编解码框架绑定在一起,所以 ,通常使用 Thrift 的时候会采取 RPC 框架的方式。但是,它的 TProtocol 编解码框架还是可以以类库的方式独立使用的。
与 Protobuf(Google的Protobuf) 比较类似的是,Thrift 通过 IDL 描述接口和数据结构定义,它支持 8种 Java 基本类型、Map、Set和 List,支持可选和必须定义,功能非常强大。因为可以定义数据结构中字段的顺序,所以它也可以支持协议的前向兼容。
二、Thrift 支持三种比较典型的编解码方式
■ 通用的二进制编解码;
■ 压缩二进制编解码;
■ TJSONProtocol:JSON 格式;
■ 优化的可选字段压缩编解码;
由于支持二进制压缩编解码,Thrift 的编解码性能表现也相当优异,远远超过 Java序列化和 RMI等。
Thrift 工作原理(实现多语言间的通信):数据的传输使用 socket(多种语言均支持),数据在以特定的格式(String等)发送,接收方按对应的格式进行解析。定义 thrift 文件,有 thrift 文件(IDL)生成双方语言的接口、Model,在生成接口和 Model 的代码中包含编解码的代码。
三、Thrift 数据/容器类型
Thrift 通过中间件语言IDL(接口定义语言)来定义 RPC 的数据类型和接口,这些内容写在以 .thrift 结尾的文件中。然后通过特殊的编译器来生成不同语言的代码,以满足不同需求的开发者。比如 java开发者,就可以生成 java代码,c++开发者可以生成 c++代码,生成的代码中不但包含目标语言的接口定义、方法、数据类型,还包含有 RPC协议层和传输层的实现代码。
Thrift 不支持无符号类型,因为很多语言不存在无符号类型,比如 Java。
■ byte:有符号字节;
■ i16:16位有符号整数;
■ i32:32位有符号整数;
■ i64:64位有符号整数;
■ double:64位浮点数;
■ string:字符串
容器类型:List、Set、Map:与 Java 中的类型类似。
四、Thrift 的协议栈结构
五、Thrift IDL 文件
【1】结构体(struct):就像 C语言一样,Thrift 支持 Struct 类型,目的就是将一些数据聚合在一起方便传输管理。
【2】枚举(enum):定义形式与 Java 的定义形式类似。
【3】异常(exception):支持自定义 exception,规则与 Struct 一致。
【4】服务(service):Thrift 定义服务相当于 java 中创建 interface 一样,创建的 service 经过代码命名之后就会生成客户端和服务端的框架代码。相当于若干个方法的集合。
【5】类型定义:支持类型C++ 一样的 typedef 定义:typedef i32 int ,后续的操作就可以使用 int 代替 i32
【6】常量(const):使用 const 关键字:const i32 MAX_RETRIES_TIME = 10
【7】命名空间:相当于 java中的 package的意思,主要的目的是组织代码。thrift 的关键字 namespace:namespace 语言名(java) 路径(com.test.thrit.demo)
【8】文件包含:Thrift 也支持文件包含,相当于C/C++ 中的 include,Java 中的 import。
【9】注释:Thrift 注释支持 shell 风格的注释,支持 C/C++ 风格的注释,既#和//开头的都可以当注释,/**/包裹的可以当做注释。
【10】可选和必选:Thrift 提供了两个关键字:required 和 optional 分别用于字段的必填和可选。
六、Thrift 安装
官网下载地址:http://thrift.apache.org/download
七、代码生成
【1】定义一个 .thrift 文件:data.thrift
【2】执行命令格式: thrift --gen java 文件路径
【3】生成目录结构如下:
【4】导入依赖的 jar 包:
八、数据传输方式
【1】TSocket:阻塞式 socket(效率底);
【2】(常用)TFramedTransport:以 Frame 为单位进行传输,非阻塞式服务中使用;
【3】TFileTransport:以文件形式进行传输;
【4】TMemoryTransport:将内存用于I/O,Java 实现时内容实际使用了简单的 ByteArraryOutPutStream;
【5】TZlibTransport:使用 Zlib 进行压缩与其他传输方式联合使用,当前无 Java 实现;
九、 Thrift 支持的服务模式
【1】TSimpleServer:简单的单线程服务模型,常用语测试;
【2】TThreadPoolServer:多线程服务模型,使用标准的阻塞式IO;
【3】TNonblockingServer:多线程服务模型,使用非阻塞式IO(需使用 TFramedTransport 传输数据)
【4】THsHaServer:(常用)THsHa 引入了线程池去处理,其模型把读写任务放到线程池去处理;Half-sync/Half-async 的处理模式,Half-aysnc 是在处理IO事件上(accept/read/write io),Half-sync 用于 handler 对 rpc 的同步处理。
十、Thrift 服务端与客户端交互
【1】服务端实现类
【2】thrift 服务端程序编写
【3】thrift 客户端程序编写
【4】测试结果(客户端/服务端)展示: