文章简介
从Thrift的C++源代码中看,thrift的设计思想,讨论跨语言优质RPC解决方案。
Thrift的诞生背景
Thrift的诞生时间大概断定为2007年左右,随着Facebook网站流量的增加和站点功能的日益丰富,已经远远超出了原有LAMP架构的处理能力,对系统服务的可伸缩性和高性能提出了技术挑战。Facebook的工程师文化趋向于选择可用的最好的工具和实现手段解决软件开发中的问题,确保简洁和高效,需要面对多语言协作的难题。然而,当时行业内还没有可选的开源解决方案,因此,Facebook设计和编写了Thrift,可伸缩跨语言服务实现。
Thrift的技术依赖(C++)
thrift代码生成工具 | flex词法分析器 | 配合多语言生成 |
bison语法分析器 | 配合多语言生成 | |
Thrift网络服务开发库 | Boost"准"标准库 | 少量运用,智能指针、多线程等 |
libevent事件驱动网络库 | 可选,支持高性能异步回调 | |
openssl加密库 | 可选,支持HTTPS协议 | |
zlib | 可选,支持报文压缩 |
表1-1 Thrift的技术依赖——需要安装的软件
Thrift的设计思想
图1-1 Thrift的多语言通讯模型抽象和多语言类型模型抽象
如表1-1所示,Thrift由两部分组成,网络服务开发库和代码生成工具。图1-1中的Transport和ServerTransport就是客户端和服务端的通讯模型抽象的基础函数,任意编程语言只要包含这些API,就能够使用自身编程语言实现一个完整的Thrift。图1-1中的基础类型和复合类型就是统一的接口数据类型,综合多种语言而设计的接口定义中间语言IDL。
图1-2 Thrift的模块化分层设计
Thrift的分层设计思想具有很强的可扩展性,能够适应生产环境中复杂的功能需求的定制化开发。对于业务开发而言,业务协议报文既可以在TCP协议上传输,也可以在HTTP/HTTPS协议上传输。基于IDL中定义的基础类型和复合类型,序列化协议层实现了数据结构的序列化和反序列化接口,并具体实现了JSON、compact和binary通讯协议。
当编写好thrift中间接口定义文件时,运行thrift命令生成指定语言的RPC代码;这其中包含了,请求数据和响应数据中各个字段的序列化和反序列化的顺序,Thrift是无版本号的协议设计,数据结构和函数入参出参都不需要版本号,取而代之的是变量编号。变量在协议中传递时,都会带上变量名称、变量类型和变量编号,在次基础上实现required和optional仅仅需要在isset中打上标记。接口调用处理层,实现了RPC函数名称和业务实现功能函数的映射关系。在服务接口层,客户端已经完全由代码生成,而服务端则仅仅生成了RPC函数的纯虚函数,只是一个桩子,需要开发编写具体的业务逻辑。
这一切的功能实现得如此的简洁和高效,笔者将它归结为IDL代码生成的优势。
参考文献
[1] Mark Slee, Aditya Agarwal and Marc Kwiatkowski. Thrift: Scalable Cross-Language Services Implementation. 2007
[2] Apache Thrift官方网站, http://thrift.apache.org
[3] Apache Thrift源代码, https://github.com/apache/thrift
[4] Lex & Yacc 官方网站, http://dinosaur.compilertools.net