think icon indicating copy to clipboard operation
think copied to clipboard

Thirft协议入门

Open bytemofan opened this issue 6 years ago • 0 comments

Thirft是什么?

Thirft是一种接口描述语言与二进制通讯协议,它被用来创建和定义跨语言的服务。

服务端常用RPC的方式进行服务之间的调用。Thirft就是facebook为“大规模语言服务开发”而开发的一个服务端RPC调用框架。它通过一个代码生成引擎联合了一个软件栈,来创建不同程度的、无缝的跨平台高效服务,支持多种后端语言,例如:Java、Go、C++、C#、C、Python,PHP、NodeJS等等。

Thirft架构

Thrift包含一套完整的栈来创建客户端和服务端程序。顶层部分是由Thrift定义生成的代码。而服务则由这个文件客户端和处理器代码生成。在生成的代码里会创建不同于内建类型的数据结构,并将其作为结果发送。协议和传输层是运行时库的一部分。

有了Thirft,就可以定义就可以定义一个服务或改变通讯和传输协议,而无需重新编译代码。除了客户端部分之外,Thrift还包括服务器基础设施来集成协议和传输,如阻塞、非阻塞及多线程服务器。栈中作为I/O基础的部分对于不同的语言则有不同的实现。

Thirft的API CS架构图: image

其中,黄色部分是用户实现的业务代码。 褐色部分是根据 Thrift 定义的服务接口描述文件生成的客户端和服务器端代码框架。 红色部分是根据 Thrift 文件生成代码实现数据的读写操作。 红色部分以下是 Thrift 的传输体系、协议以及底层 I/O 通信,使用 Thrift 可以很方便的定义一个服务并且选择不同的传输协议和传输层而不用重新生成代码。

Thirft定义接口描述文件时可使用的数据类型

  • 基本类型
    • bool:布尔值,true或false
    • byte:8位有符号整数
    • i16: 16位有符号整数
    • i32: 32位有符号整数
    • i64: 64位有符号整数
    • double: 64位浮点数
    • string: 未知编码文本或二进制字符串
  • 结构体类型
    • struct:定义公共的对象,类似C语言中的结构体定义
  • 容器类型
    • list
    • set
    • map
  • 异常类型
    • expection
  • 服务类型
    • service: 对应的服务类

Thirft支持的协议

Thrift 可以让用户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为文本 (text) 和二进制 (binary) 传输协议,为节约带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目 / 产品中的实际需求。

常用的通讯协议有:

  • TBinaryProtocol 简单二进制格式,没有为空间效率而优化
  • TCompactProtocol 更紧凑的二进制格式
  • TJSONProtocol 使用JSON格式
  • TDenseProtocol 与TCompactProtocol类似,只是将元信息剥离。
  • TDebugProtocol 人类可读的文本格式,协助调试用
  • TSimpleJSONProtocol 只提供 JSON 只写的协议,适用于通过脚本语言解析

常用的传输协议有:

  • TSocket 使用阻塞式 I/O 进行传输,是最常见的模式
  • TFramedTransport 使用非阻塞方式,按块的大小进行传输
  • TNonblockingTransport 使用非阻塞方式,用于构建异步客户端
  • TFileTransport 该传输协议会写文件
  • TZlibTransport 用zlib执行压缩,用于连接另一个传输协议。
  • TSimpleServer 单线程服务器,它使用标准的阻塞I/O。测试时很有用
  • TThreadPoolServer 多线程服务器,它使用标准的阻塞I/O
  • TMemoryTransport 使用存储器映射输入输出

针对不同的传输协议,服务端也提供了不同的服务与之对应,常用的服务有:

  • TSimpleServer 单线程服务器端使用标准的阻塞式 I/O
  • TThreadPoolServer 多线程服务器端使用标准的阻塞式 I/O
  • TNonblockingServer 多线程服务器端使用非阻塞式 I/O(TFramedTransport必须和这个配套使用)

Thirft优点

  • 跨语言序列化的代价更低,因为它使用二进制格式
  • 简洁,没有XML配置,没有编码框架
  • 绑定自然
  • 应用层通讯格式与序列化层通讯格式是完全分离的。它们都可以独立修改
  • 预定义的序列化格式包括:二进制格式、对HTTP友好的格式,以及紧凑的二进制格式
  • 可以用于跨语言文件序列化
  • 协议使用软版本号机制软件版本管理,Thrift不要求一个中心化的和显式的版本号机制,例如主版本号/次版本号。松耦合的团队可以轻松地控制RPC调用的演进。
  • 没有构建依赖也不含非标准化的软件。不存在不兼容的软件许可证混用的情况。

如何使用Thirft?

首先,引入Thirft协议支持包,各语言引入方式不一,参考官网

其次,要创建一个Thrift服务,必须写一些Thrift文件来描述它,为目标语言生成代码,并且写一些代码来启动服务器及从客户端调用它。Thirft描述文件示例:

enum PhoneType {
 HOME,
 WORK,
 MOBILE,
 OTHER
}

struct Phone {
 1: i32 id,
 2: string number,
 3: PhoneType type
}

以Java为例: image 客户端和服务器端部署时,需要用到公共的 jar 包和 java 文件,如图“Common file”区域,其中 Hello.java 由 Hello.thrift 编译而来。在服务器端,服务必须实现 Hello.Iface 接口,同时要包括服务器的启动代码 HelloServiceServer.java。在客户端,包括客户端调用服务的代码 HelloServiceClient.java。客户端和服务器通过 Hello.java 提供的 API 实现远程服务调用。

服务端调用时序图: image

客户端调用时序图: image

参考

https://zh.wikipedia.org/wiki/Thrift#%E6%9E%B6%E6%9E%84 https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/index.html

bytemofan avatar Sep 10 '18 06:09 bytemofan