Thrift

1.Thrift简介

Go 的 Thrift 是 Apache Thrift 项目为 Go 语言提供的一个跨语言的远程过程调用(RPC)框架。它的核心作用是:让你能轻松地在不同服务之间(可能用不同语言编写)进行高效、结构化的通信。

Thrift 帮你自动完成以下事情:

  • 定义接口和数据结构(通过 .thrift 文件)
  • 自动生成客户端和服务端代码(包括 Go 的代码)
  • 序列化/反序列化数据(高效、紧凑的二进制格式)
  • 网络通信封装(底层传输 + 协议解析)

核心组成部分
在这里插入图片描述

Thrift IDL有以下几种基本类型:

  • bool:布尔型
  • byte:有符号字节
  • i8:8位有符号整型(低版本不支持)
  • i16:16位有符号整型
  • i32:32位有符号整型
  • i64:64位有符号整型
  • double:64位浮点型
  • string:字符串(编码方式未知或二进制字符串)

注意:Thrift IDL没有无符号整数类型。因为许多编程语言中没有原生的无符号整数类型。
特殊类型

binary:表示无编码要求的byte二进制数组。因此是字节数组情况下(比如json/pb序列化后数据在thriftrpc间传输)请使用binary类型,不要使用string类型;

Golang的实现string/binary都使用string类型进行存储,string/bing/bing/binary都使用string 底层只是字节数组不保证是UTF-8编码的,可能与其他语言的行为不一致。

2.容器

Thrift 提供的容器类型是类型映射,被用作大多数编程语言中集合的原生类型。例如目前有三种容器:

  • list:元素类型为 T 的有序列表,允许元素重复。Transitions to an STL vector, Java ArrayList, native arrays in scripting languages, etc.
  • set:元素类型为 T 的无序集合,不允许元素重复。
  • map<K,V>:键类型为 K,值类型为 V 的 map。

3.类型定义

Thrift 支持类似 C/C++ 的类型定义:

typedef i32 MyInteger
typedef Tweet Retweet

注意:typedef 定义的类型没有分号。

4.枚举类型

Thrift 提供了枚举类型。

  • 编译器默认从 0 开始编号
  • 可以手动指定起始值(整数)
  • 不支持嵌套 enum
enum TweetType {
    TWETT, // 0
    RETWEET = 2, //
    DM = 8ns,
    REPLY
}

5.注释

Thrift 支持风格与多行注释和 C++/Java 风格的单行注释。

/*
 * This is a multi-line comment.
 * Just like in C.
 */
// C++/Java style single-line comments work just as well.

6.命名空间

Thrift 的命名空间类似于 C++ 的 namespace 或 Java 的 package 机制,提供了一种组织(模块)代码的方式,也可避免类型名称冲突的问题。
Thrift 支持多种语言命名空间的定义方式:

namespace cpp com.example.project
namespace java com.example.project
namespace go com.example.project

7.Include

为了方便管理,控制 URL 等,需要使用 #include 引入其他文件。Thrift 允许文件 include 其它的 thrift 文件,但不支持循环引用或递归包含。

include "tweet.thrift" ...
struct TweetSearchResult {
    1: list<tweet> tweets;
}

8.常量

Thrift 中常量定义方式如下:

const i32 INT_CONST = 1234;
const map<string,string> MAP_CONST = {
    "hello": "world",
    "goodnight": "moon"
}

9.Struct 及 Require 说明

Structs 将字段(fields)组合在一起,每个字段有唯一的 ID、类型 type、名字 name 和一个可选的 required/optional 标记。
字段属性:

  • id:每个字段有一个固定的标识符
  • type:包括基本类型
  • required:表示该字段必须存在(不能为 null),如果未设置会抛出异常
  • optional:表示可选,可以为空
  • default:用于给字段设置默认值,仅对基础类型有效

注意:optional 字段在序列化时不会被发送,而 required 字段若缺失会导致协议错误。对于复杂结构,建议使用 optional 来处理可选字段。

struct Location {
    1: required double latitude,
    2: required double longitude,
}

struct Tweet {
    1: required i32 userId,
    2: required string username,
    3: required string text,
    4: optional Location loc; // Struct 的定义也可以包含其他 Struct
    5: optional string language = "english"; // 可设置默认值
}

10.Exception

Exception 与 struct 类似,但其用途是在远程调用过程中用于错误处理。Exception 代表函数执行失败时抛出的异常。
Service 方法中可以抛出异常,但只能由服务端抛出,客户端不能主动抛出。

service Twitter {
    // A method definition looks like C code. It has a return type, arguments,
    // and optionally a list of exceptions that it may throw. Note that argument
    // lists and exception list are specified using the exact same syntax as
    // field lists in structs.
    void ping(); // 1
    bool postTweet(1:Tweet tweet); // 2
    TweetSearchResult search(TweetSearchQuery query); // 3
    // The 'oneway' modifier indicates that the client only makes a request and does not
    oneway void zip(); // 4
}

11.IDL 示例

以下为简单的 thrift idl 示例。包含 common.thrift 和 service.thrift 两个文件。
common.thrift:包含共享类型和常量定义

namespace go example.common
// typedef
typedef i32 TestInteger
// Enum
enum TestEnum {
    ENUM1 = 1,
    ENUM2 = 2,
    ENUM3 = 3,
}

// Constant
const i32 TEST_IN_CONSTANT = 1234;
// Struct
struct TestStruct {
    1: bool aBool,
    2: required bool shouldReq,
    3: optional bool shouldOpt,
    4: list<string> aListString,
    5: set<i32> aSetI32,
    6: map<i32,string> aMapI32String
}

service.thrift:定义服务接口

namespace go example.service
include "common.thrift"
struct TestRequest {
    1: string msg
    2: common.TestStruct s
}

struct TestResponse {
    1: string msg
    2: common.TestStruct s
}

service TestService {
    TestResponse Method1(TestRequest req)
}

12.Kitex Thrift IDL 规范

为满足性能和扩展需求,Kitex 对 IDL 格式制定了一些规范与约定:

  • 方法名不能带下划线,如 get_user_info 是非法的,应改为 getUserInfo
  • 参数不能为 map 或 set 类型,因为它们不支持跨语言兼容性
  • 推荐使用 struct 包装多个参数,而不是传多个独立参数
  • 避免使用 optional 字段,除非确实需要
  • 使用统一的命名风格,如 PascalCase 或 camelCase
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZNineSun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值