Thrift 是一个多语言 RPC 接口生成工具,使用 IDL 描述接口的 schema,然后用 Thrift 的 IDL 编译器转换得到目标语言的 RPC 接口。
Thrift 目前支持 28 种语言,涵盖了绝大部分的主流语言。
BFF
RPC 面向服务,相比 HTTP 封装更完整、性能更好,在大厂内部普遍使用。
RPC 服务的粒度通常比较小,前端的一个请求往往需要调用多个 RPC 接口,为了简化前端的调用,可以增加一层 BFF (Backend For Frontend),通常是 Node 后端 (比如 Nest)。BFF 封装前端需要的接口,代替前端调用相应的多个 RPC 接口,拼接获取的数据并返回给前端。
前端写 BFF 调用 RPC 接口时,需要能够读懂 IDL 的接口声明,基本上了解到这一步就够了,使用 Thrift 生成 RPC 接口是服务端的工作。
IDL
IDL (Interface Description Language,接口描述语言) 用于描述 RPC 接口的 schema,包括函数名、参数列表、返回值类型。
注释
IDL 支持 3 种类型的注释:
#///* */
数据类型
| 数据类型 | 说明 |
|---|---|
bool | 布尔值,1 个字节 |
i8 | 1 字节有符号整数 |
i16 | 2 字节有符号整数 |
i32 | 4 字节有符号整数 |
i64 | 8 字节有符号整数 |
double | 8 字节浮点数 |
string | 字符串 |
binary | 二进制数据,字节数组 |
map<t1,t2> | t1 到 t2 类型的映射 |
list<t1> | t1 类型的有序列表 |
set<t1> | t1 类型的集合 |
导入
IDL 支持用 include 导入其他 .thrift 文件。
include "shared.thrift"
类型定义
IDL 支持用 typedef 定义自己的类型,与 C 的语法一致。
typedef i32 MyInteger
常量
IDL 用 const 定义常量。
const i32 INT32CONSTANT = 9853
const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
枚举
IDL 用 enum 定义枚举类型,本质是 i32,与 C 的语法一致,默认从 1 开始。
enum Operation {
ADD = 1,
SUBTRACT = 2,
MULTIPLY = 3,
DIVIDE = 4
}
结构
IDL 用 struct 定义结构体,每个字段由 4 个部分组成:
- 整数 ID
- 数据类型
- 字段名
- 默认值 (可选)
struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,
}
字段可以是可选的,用 optional 标注。
异常
IDL 允许使用与 struct 相同的语法描述异常数据,使用 exception 关键字。
exception InvalidOperation {
1: i32 whatOp,
2: string why
}
服务
IDL 中的服务类似于面向对象里的类,使用 service 关键字指定一个服务名,可以用 extends 继承其他服务。
服务包含若干个函数,函数的语法与 C 类似,包括:
- 返回值类型
- 函数名
- 参数列表
- 每个参数的语法与
struct字段相同
- 每个参数的语法与
service Calculator extends shared.SharedService {
void ping(),
i32 add(1:i32 num1, 2:i32 num2),
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
// oneway 表示客户端不需要响应,返回值类型必须为 void
oneway void zip()
}