初探thrift | 青训营

112 阅读3分钟

Thrift是由Facebook开发的,现由Apache管理的开源RPC框架。Thrift作为接口描述语言,被用于定义和创建跨语言的服务。通过代码生成引擎封装了不同语言间IO、网络传输的细节,以创建无缝的跨平台、跨语言服务。

用法

语法

说到一门语言必然要提到它的语法。Thrift作为一种通用的IDL,其语法格式较为简单,不仅提供了绝大多数语言的函数声明格式、基本类型,同时也对不同语言的特点提供了不同的特性。

基本类型

bool: true/false
byte: 8 位有符号整数
i16:16 位有符号整数
i32:32 位有符号整数
i64:64 位有符号整数
double:64 位浮点数
string:字符串

Typedef

用法类似于CPP,支持了类型别名。如:typedef i32 int

enum

与大多数语言的枚举是一个目的。但是Thrift中Enum只支持整数值。如下:

enum Fruit {
  Apple = 1,
  Banana = 2,
  Cherry = 3,
}

Struct/Union

需要注意的是Thrift并不直接使用基本类型(建议这样使用,良好的语义在团队开发中可以起到重要的作用),我们往往会针对不同的接口设计独立的结构体。Union则是针对特定语言的结构,使用方式与struct类似。如:

struct EchoRequest {
    1: string message
}
struct EchoResponse {
    1: string message
}

struct后紧跟类型名以及{},括号内是各成员的类型及名称,称为域,每行之间以逗号分开。域前有正整数标识符,可以不连续,但一经定义,最好不要修改,否则可能会导致新旧代码所生成的接口参数顺序的不同,导致兼容性问题。
之后则是域的限定,由required/optional修饰。
其中,若以required修饰的,则在后面的构造中必须赋值,否则会认为异常。

容器

Thrift提供了三种容器,分别是listsetmap
如:list<T>,其中,T为任意类型。
需要注意的是,一方面某些语言不支持容器中有复杂类型,另一方面Thrift对复杂类型的解析可能会出错。所以容器中最好使用基本类型。

异常

用法与struct类似,是为异常处理专门设计的。

Header

一个Thrift文件可以包含任意多个(包括0个)Header。它描述了这个接口所引用的库、命名空间等文件。如:IncludeCppIncludeNamespace等。其中Include只是简单地引入了其他Thrift文件的内容;CppInlcude则表示在生成的CPP文件中包含所引用的CPP文件;NameSpace组织了代码,可以简单的认为对不同语言的分类处理。

注释

兼容(缝)了许多类型的注释。如:

//这是注释

/*这也是注释*/

#这还是注释

服务(service)

接口定义是thrift的一大重点。它实质上是一个包含函数名的列表。定义服务时,先以service开头,再接服务名,然后是一对花括号。
内部则是一个个接口的定义,以 返回值 接口名(参数编号:参数 参数名,...) 异常 为格式。如:

serivce EchoService{
    EchoResponse echo(1: EchoRquest msg) throw (1: error err)
}

注意到,每次只能返回一个变量。异常是可选的。

代码生成

使用Thrift提供的代码生成工具,同时也可以使用Kitex进行go的生成。如

thrift --gen cpp echo.thrift

架构

Thrift采用了典型的C/S架构。通过上述部分来关联客户端和服务端。

thrift-02.png (图片来源于网络)
整体架构可以分为5层。 业务逻辑
服务,包含对应服务及依赖
TProtocol,协议层
TTransports,传输层
I/O传输。