Thrift

346 阅读4分钟

建议先阅读此篇文章rpc-demo

简介

Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。 它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。
Thrift实现了一种接口描述语言和二进制通讯协议,来定义和创建跨语言的服务。它被当作一个RPC框架来使用

Thrift架构与使用方法

如果现在要实现一个除法divide的RPC接口服务:

float divide(1:int num1,2:int num2=1) => InvalidOperation

Thrift安装

// mac
brew install thrift

Thrift语法

基本类型

  • bool:布尔
  • byte:8位有符号整数
  • i16:16位有符号整数
  • i32:32位有符号整数
  • i64:64位有符号整数
  • double:64位浮点数
  • string: 字符串
  • binary:二进制数据

容器类型

可以包含多个数据(元素)的类型。

  • list<type>:元素为type类型的列表,与python的list对应,如:list<double>
  • set<type>:元素为type类型且唯一的集合,与python的set对应,如:set<i32>
  • map<type1,type2>:键为type1类型值为type2的映射,与python的dict对应,如:map<string,string>

常量类型

const 常量类型 常量名称 = 常量值

const i32 INT32CONSTANT = 9853
const map<string,string> MAPCONSTANT = {'hello':'world'}

枚举类型

enum Operation {
    ADD = 1,
    SUBTRACT = 2,
}

结构体类型

struct,封装一组不同类型的数据,与Python的类对应,如

struct Work {
    1: i32 num1 = 0,
    2: i32 num2,
    3: Operation op,
    4: optional string comment,
}

optional关键字表示该字段值可选,如果构建的结构体类型数据中可选字段没有设置值,则在编码生成的消息数据中不会包含可选字段。

异常类型

exception,可以自定义异常中包含的数据内容,与Python中的类对应,如:

exception InvalidaOperation {
    1: i32 whatOp,
    2: string why
}

typedef

使用typedef 可以为类型起别名,如:

typedef i32 MyInteger

服务接口

service,定义服务接口的方法和参数,如:

service BasicService {
    // 返回值 | 方法名 | 参数 | 异常
    double divide(1:i32 num1, 2:i32 num2) throws (1:InvalidaOperation e)
    oneway void ping()
}

说明:

  • 方法可以不带参数,如带参数,需要指明参数的序号和参数的类型
  • 方法名前必须指明返回值类型,void表示没有返回类型
  • oneway表示客户端发起请求后不再等待响应返回,oneway方法必须返回void类型
  • throws表示可能抛出的异常

服务继承

使用extends可以继承扩展另一个服务,如:

include "base.thrift"
service Calculate extends base.BasicService {
    i32 calculate(1:base.Work w) throws (1:base.InvalidaOperation e)
}

编译

使用thrift命令来编译接口定义文件,生成程序代码

// thrift --gen 语言 文件名
thrift --gen go ./src/thrift/go.thrift
thrift -r --gen go ./src/thrift/go.thrift

对于有继承服务的接口定义文件,可以添加-r参数,生成所有相关接口程序

协议与传输选择

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

协议类型

  • thrift.protocol.TBinaryProtocol
// 二进制编码格式进行数据传输
from thrift.protocol import TBinaryProtocol,TCompactProtocol

// 客户端构建方式
protocol = TBinaryProtocol.TBinaryProtocol(transport)
// 服务端构建方式
pfactory = TCompactProtocol.TBinaryProtocolFactory()
  • thrift.protocol.TCompactProtocol (推荐)
// 高效的/密集的二进制编码格式进行数据传输
from thrift.protocol import TCompactProtocol,TBinaryProtocol

// 客户端构建方式
protocol = TBinaryProtocol.TCompactProtocol(transport)
// 服务端构建方式
pfactory = TCompactProtocol.TCompactProtocolFactory()
  • thrift.protocol.TJSONProtocol
// 使用JSON的数据编码协议进行数据传输
from thrift.protocol import TJSONProtocol

// 客户端构建方式
protocol = TJSONProtocol.TJSONProtocol(transport)
// 服务端构建方式
pfactory = TJSONProtocol.TJSONProtocolFactory()

传输方式

  • thrift.transport.TSocket
// 使用阻塞式I/O进行传输,是最常见的模式
from thrift.transport import TSocket

// 客户端构建方式
transport = TSocket.TSocket('127.0.0.1',8000)
// 服务端构建方式
transport = TSocket.TServerSocket('127.0.0.1',8000)
  • thrift.transport.TTransport.TBufferedTransport (推荐)
// 原始的socket方式效率不高,Thrift提供啦封装的加了缓存的传输控制
from thrift.transport import TSocket

// 客户端构建方式
transport = TSocket.TSocket('127.0.0.1',8000)
transport = TTransport.TBufferedTransport('127.0.0.1',8000)
// 服务端构建方式
transport = TSocket.TServerSocket('127.0.0.1',8000)
tfactory = TTransport.TBufferedTransportFactory()

服务端类型

Thrift提供的常见服务端类型有以下几种:

  • thrift.server.TServer.TSimpleServer 单线程服务器
  • thrift.server.TServer.TThreadedServer 多线程服务器
  • thrift.server.TServer.TThreadPoolServer 线程池服务器
  • thrift.server.TServer.TForkingServer 多进程服务器 我们以线程池服务器为例,其它方式相同

参考视频
demo-box