之所以想写 Thrift 和 Protobuf,是因为项目新一轮的微服务和服务容器化改造,弃用了原来用的 Thrift,全部统一改成了使用 Protobuf,如果问到为什么要弃用功能强大的 Thrift,而改用了 Protobuf,因为 Protobuf 是 Google 爸爸推出的,哈哈哈,其实理由只有一条,Protobuf 官方文档较为丰富,生态维护的也很好,而 Thrift 官方文档较少,没有 API 文档,而且 google 搜索 protocol buffer 次数和搜索 apache thrift 的不是一个量级。
跨语言的通讯协议有很多:http, xml, json, avro, protobuf, thrift等等。对于 http, xml 和 json 我就不做过多描述了,参考相关文档就可以了。特别是 json,如今在各种系统前后台通讯中,应用非常广泛。我将重点介绍两种目前在大型系统中,应用比较普遍的两种通讯协议:Thrift 和 Protobuf。
对于这两种通讯协议而言,首推的应该是 thrift,根据官方描述,thrift 不仅有对于协议封装和解析的处理,而且有完备的通讯框架的实现,完全封装了底层通讯,对于使用者,只要在框架的客户端和服务器接口回调中,处理逻辑就可以了。
Thrift 是一个跨语言的服务部署框架,最初由 Facebook 于 2007 年开发,2008 年进入 Apache 开源项目。Thrift 通过一个中间语言(IDL, 接口定义语言)来定义 RPC 的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 和 OCaml),并由生成的代码负责 RPC 协议层和传输层的实现。
Thrift 实际上是实现了 C/S 模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在 Thirft 描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中 protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和 transport(传输层,定义数据传输方式,可以为 TCP/IP 传输,内存共享或者文件共享等)被用作运行时库。
Thrift 支持二进制,压缩格式,以及 json 格式数据的序列化和反序列化。这让用户可以更加灵活的选择协议的具体形式。更完美的是,协议是可自由扩展的,新版本的协议,完全兼容老的版本!
那么 thrift 有没有缺点呢,有,而且很严重!但不影响使用,因为此框架的缺点不在于其程序本身,而在于其文档的缺失!包括中文的,及英语的相关文档。要彻底的理解和熟练的把握 thrift 只有一个办法,读 thrift 的代码,通读!我很乐于做这样的事,因为读代码,而且是高质量的代码,是一件非常有乐趣的事情,这对于一个程序员来讲,没有什么。当然,本着普及的需要,文档的完善化,确实需要大大的加强。当然,我也相信,thrift 的文档,会日渐完善,因为现在国内的热心程序开发者,开源软件的爱好者越来越多,使用的同时,着手 thrift 文档的补充工作,是很多人愿意做的,而且也是很有成就感的事情。
相比于,thrift 文档的匮乏,protobuf 的文档可称非常完备。这一点,我认为 google 开源出来的东西,确实要比facebook,在使用指南和文档完备上高出一个档次。
protobuf 是 google 提供的一个开源序列化框架,类似于 XML,JSON 这样的数据表示语言,其最大的特点是基于二进制,因此比传统的 XML 高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,可以很方便的对其基于二进制的协议进行扩展,并且很方便的能让新版本的协议兼容老的版本。如果说 xml 太臃肿,json 易解析,比 xml 更高效,易扩展,那么protobuf 可以说,相对于 json 更高效,更易扩展,而且协议的保密性更强。并且 protobuf 是跨语言的,可以支持c(c++), java, python 等主流语言,非常方便大系统的设计。protobuf 号称也有 service,可以基于其 service 的接口和回调,来完成客户端和服务器的逻辑。但是,目前版本 service 还仅仅停留在接口层,其底层的通讯,还需要自己实现,这点确实远不如 thrift 完备。
protobuf 在 google 中是一个比较核心的基础库,承担着 google 海量服务器间的通讯协议设计。在多功能,跨语言的海量系统中,如此高效,简洁,可自由扩展的通讯框架,可谓经典。
不愧是yafei