1.什么是thrift
thrift是一个软件框架,⽤来进行可扩展且跨语言的服务的开发。它结合了功能强⼤的软件堆栈和代码⽣成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间⽆缝结合的、高效的服务。他是跨语言的、支持多种协议、适用各种应用场景。
2.Thrift 的组成
(1)类型系统以及 IDL 编译器:负责由用户给定的 IDL 文件生成相应语言的接口代码。
(2)TProtocol:实现 RPC 的协议层,可以选择多种不同的对象串⾏化方式,如JSON, Binary。
(3)TTransport:实现 RPC 的传输层,同样可以选择不同的传输层实现,如socket, ⾮非阻塞的 socket, MemoryBuffer 等。
(4)TProcessor:作为协议层和用户提供的服务实现之间的纽带,负责调⽤服务实现的接⼝。
(5)TServer:聚合 TProtocol, TTransport 和 TProcessor 几个对象,构建成完成的服务器。
3.IDL
IDLthrift用一种中间语⾔(IDL,接⼝口定义语⾔)来定义 RPC 的接口和数据类型,然后通过⼀个编译器来⽣成不同语⾔的代码(如C++, Java, Python等),并由生成的代码来负责 RPC 协议层和传输层的实现。
生成语⾔命令(java&php):
java: thrift -gen -r java xxx.idl
php: thrift -gen -r php xxx.idl
对于thrift,就是用 “ .thrift ”结尾。
美团有一个可视化的thrift生成工具:http://genthrift.sankuai.com/,开发中用这个比较方便。
Thrift 脚本可定义的数据类型包括以下几种类型:
(1)基本类型:
bool:布尔值,true 或 false,对应 Java 的 boolean
byte:8 位有符号整数,对应 Java 的 byte
i16:16 位有符号整数,对应 Java 的 short
i32:32 位有符号整数,对应 Java 的 int
i64:64 位有符号整数,对应 Java 的 long
double:64 位浮点数,对应 Java 的 double
string:未知编码⽂文本或⼆二进制字符串,对应 Java 的 String
(2)结构体类型:
struct:定义公共的对象,类似于 C 语⾔言中的结构体定义,在 Java 中是一个 JavaBean。
语法:
struct UserGradeInfo {
1: required string UserName = "Anonymous";
2: required i16 UserGrade = 0;
}
结构体中每一个域都有一个正整数标识符,这个标识符并不要求连续,但一旦定义,不建议再进行修改。
另外,每个域前都会有required或optional的限定,前者表示是必填域,后者则表示是可选域。
如果一个域设置了required,但是在实际构造结构体时又没有给这个域赋值,那么thrift会认为这是一个异常。
如果一个域设置为optional且在构造结构体时没有给这个域赋值,那么在使用这个结构体时,就会忽略掉这个optional的域。
(3)容器类型:
list:对应 Java 的 ArrayList
set:对应 Java 的 HashSet
map:对应 Java 的 HashMap
(4)异常类型:
exception:对应 Java 的 Exception
语法与上述的struct的语法是一样的。
(5)服务类型:
service:对应服务的类(这里定义的是接口,需要自己去实现)。
每个服务,都包括了若干个函数,每个函数包括了若干参数和一个返回值(返回值可以是void)。
语法:
service Hello{
string hello(1:string para)
bool helloBoolean(1:bool para)
oneway void helloViod()
}
返回值为void的函数,你可以在函数名前加上oneway标识符,将此函数以异步模式执行,这样在调用此函数后,函数会立即返回,在构建异步服务器客户端的时候能明显提高性能。
(6)同时支持(C++中的)类型重定义
typedef i32 MyInteger // a
typedef T ReT // b
(7)命名空间与include属性:
Thrift支持对.thrift文件中的类型设定namespace,这样可以有效避免名字冲突。这种机制在C++中也叫做namespace,而在Java中叫做Package。thrift支持针对不同的语言设置不同的namespace,比如下面的例子。thrift会在生成不同语言代码时,进行相应的设置。
namespace cpp tutorial
namespace go tutorial
namespace java tutorial
namespace php tutorial
namespace perl tutorial
//类似与C语言的引用方便引用相同的文件
/* fb303.thrift是facebook的 idl文件,开发的服务继承fb303中的服务会与很多方便的接口使用*/
include 'fb303.thrift'
service Hello extends fb303.FacebookService{
string hello(1:string para)
bool helloBoolean(1:bool para)
}
4.协议
Thrift 可以让⽤户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为:文本 (text) 和⼆二进制 (binary) 传输协议,为节约带宽,提⾼高传输效率,⼀般情况下使⽤用⼆进制类型的传输协议为多数,有时还会使⽤基于⽂本类型的协议,这需要根据项目 / 产品中的实际需求。
常⽤用协议有以下⼏几种:
1.TCompactProtocol —— 高效率的、密集的二进制编码格式进行数据传输
2.TBinaryProtocol —— ⼆进制编码格式进⾏数据传输
3.TJSONProtocol —— 使⽤用 JSON 的数据编码协议进⾏行数据传输
4.TSimpleJSONProtocol —— 只提供 JSON 只写的协议,适⽤于通过脚本语言解析
5.传输层
常⽤用的传输层有以下几种:
1.TSocket —— 使⽤阻塞式 I/O 进⾏行传输,是最常见的模式
2.TFramedTransport —— 使用非阻塞⽅式,按块的⼤大⼩小进行传输(若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型)
3.TNonblockingTransport —— 使用非阻塞方式,⽤于构建异步客户端
6.服务端类型
常见的服务端类型有以下⼏种:
1.TSimpleServer —— 单线程服务器端使用标准的阻塞式 IO
2.TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O
3.TNonblockingServer —— 多线程服务器端使⽤非阻塞式 I/O
4.TThreadedSelectorServer —— 多线程半同步半异步。