Thrift入门

简介

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入门_第1张图片
Thrift的栈结构

使用

快送入门

根据官网,使用Thrift前需要下载Thrift并且构建和安装Thrift编译器。
在使用Thrift进行编程时,需要以下几步(详细过程可见Apache Thrift Tutorial):

  1. 创建.thrift文件
  2. 使用Thrift编译器编译为特定语言的源码
  3. 根据源码实现服务的功能

其实,如果你是一个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(对应Java的ArrayList)
  • 无序不可重复:set(对应Java的HashSet)
  • 关联容器:map(对应Java的HashMap)

可定制数据类型

结构体类型

struct关键字定义,需要给字段提供数字标签,示例如下:

struct PersonVo{
    1:required i32 id,
    2:required string name,
    3:required double wealth
}

说明:

  1. 字段可以采用=来设置默认值。
  2. 数字标签不要轻易修改。在修改时可以考虑新加一个数字标签,丢弃原有的字段。
  3. 字段前标识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。
  • ...

参照

  • 和 Thrift 的一场美丽邂逅
  • Thrift学习笔记—IDL基本类型
  • 维基百科 - Thrift
  • Apache Thrift - 可伸缩的跨语言服务开发框架

你可能感兴趣的:(Thrift入门)