简介
Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。
它通过一个代码生成引擎联合了一个软件栈,来创建不同程度的、无缝的跨平台高效服务,可以使用C#、C++(基于POSIX兼容系统)、Cappuccino、Cocoa、Delphi、Erlang、Go、Haskell、Java、Node.js、OCaml、Perl、PHP、Python、Ruby和Smalltalk。
另外,Thrift早期由Facebook开发,目前已成为Apache软件基金会的开源项目。
基本架构
类似于计算机网络,Thrift包含一套完整的栈来创建客户端和服务端程序。
- 顶层部分是由Thrift定义生成的代码。而服务则由这个文件客户端和处理器代码生成。在生成的代码里会创建不同于内建类型的数据结构,并将其作为结果发送。
- 协议层和传输层是运行时库的一部分。有了Thrift,就可以定义一个服务或改变通讯和传输协议,而无需重新编译代码。除了客户端部分之外,Thrift还包括服务器基础设施来集成协议和传输,如阻塞、非阻塞及多线程服务器。
- IO层在栈中作为基础部分对于不同的语言则有不同的实现。
使用
快送入门
根据官网,使用Thrift前需要下载Thrift并且构建和安装Thrift编译器。
在使用Thrift进行编程时,需要以下几步(详细过程可见Apache Thrift Tutorial):
- 创建
.thrift
文件 - 使用Thrift编译器编译为特定语言的源码
- 根据源码实现服务的功能
其实,如果你是一个Java开发者,使用Thrfit有一个更好的方式:借助Swift(并不是指苹果的Swift语言)。使用Swift,你可以告别书写thrift文件并且进行多余的一步编译,而且也不用忍受由thrift生成的冗长的Java文件,一切都可以用Java代码和注解搞定😎
样例代码thrift_demo已提交码云
Thrift IDL
IDL即为Interface Description Language,对于Thrift有其特定的语法。详细内容可以参考:Thrift interface description language
PS:若采用Jetbrains出品的IDE,可以安装Thrift Support插件来对Thrift语法做出支持。
原有数据类型
基本类型
- 布尔型:bool
- 整型:byte、i16、i32、i64
- 浮点型:double
- 字符串:string(utf8编码)
容器类型
- 有序可重复:list<t>(对应Java的ArrayList)
- 无序不可重复:set<t>(对应Java的HashSet)
- 关联容器:map<k,v>(对应Java的HashMap)
可定制数据类型
结构体类型
由struct
关键字定义,需要给字段提供数字标签,示例如下:
struct PersonVo{
1:required i32 id,
2:required string name,
3:required double wealth
}
说明:
- 字段可以采用
=
来设置默认值。 - 数字标签不要轻易修改。在修改时可以考虑新加一个数字标签,丢弃原有的字段。
- 字段前标识
required
表示,该字段必填,自然传输时必然会序列化;字段前无标识,表示可以不填充,但一定会序列化;字段前标识optional
表示该字段,可以不填充,并且不填充也不会序列化。
异常类型
异常类型的定义和结构体基本相同,但采用exception
作为关键字。
枚举类型
采用enum
作为关键字定义,示例如下:
enum ColorEnum{
WHITE = 0;
BLACK = 1;
BLUE = 2;
}
常量类型
采用const
关键字定义,示例如下:
const i32 INT_CONST = 1234;
服务类型
使用service
关键字定义,用于描述接口,类似于Java中的接口文件。示例如下:
service PersonService {
PersonDomain.PersonVo get(1:i32 id);
oneway void add(1:PersonDomain.PersonVo pv);
}
说明:
- 所有的参数都是
const
类型,不能作为返回值 -
oneway
关键字用来表示client发出请求后不必等待回复(非阻塞)直接进行下面的操作。所以其返回值一定为void
。 - 继承类必须实现这些方法。
- 服务支持继承,一个service可使用
extends
关键字继承另一个service。 - 服务中的函数不支持重载。
文件间关系
定义本文件的所处的命名空间可以采用namespace
关键字,其效果同Java中的包。使用命名空间后需指定语言类型,如java。示例如下:
namespace java demo.thrift
使用其他文件的内容需要使用include
后接其他文件名,其他文件名需要用单引号修饰。示例如下:
include 'PersonDomain.thrift'
其他
- Thrift支持C多行风格和Java/C++单行风格。
-
typedef
用于定义数据结构别名
传输体系
传输体系由传输协议和传输方式构成,具体内容在和 Thrift 的一场美丽邂逅一文中有更为详细的说明,这里就是粗略枚举一些。
传输协议
- TBinaryProtocol:是Thrift的默认协议,使用二进制编码格式进行数据传输,基本上直接发送原始数据
- TCompactProtocol:压缩的、密集的数据传输协议,基于Variable-length quantity的zigzag 编码格式
- TJSONProtocol:以JSON (JavaScript Object Notation)数据编码协议进行数据传输
- TDebugProtocol:常常用以编码人员测试,以文本的形式展现方便阅读
- ...
传输方式
- TFileTransport:该传输协议会写文件。
- TFramedTransport:当使用一个非阻塞服务器时,要求使用这个传输协议。它按帧来发送数据,其中每一帧的开头是长度信息。
- TMemoryTransport:使用存储器映射输入输出。(Java的实现使用了一个简单的
ByteArrayOutputStream
。) - TSocket:使用阻塞的套接字I/O来传输。
- TZlibTransport:用zlib执行压缩。用于连接另一个传输协议。
- ...
服务器
Thrift自带了一些好用的服务器程序,以Java为例,大致有下面这些:
- TNonblockingServer:一个多线程服务器,它使用非阻塞I/O(Java的实现使用了NIO通道)。TFramedTransport必须跟这个服务器配套使用。
- TSimpleServer:一个单线程服务器,它使用标准的阻塞I/O。测试时很有用。
- TThreadPoolServer:一个多线程服务器,它使用标准的阻塞I/O。
- ...
网友评论