# 介绍

Thrift 最初由 Facebook 开发,而后捐献给 Apache,目前已广泛应用于业界。Thrift 正如其官方主页介绍的,“是一种可扩展、跨语言的服务开发框架”。简而言之,它主要用于各个服务之间的 RPC 通信,其服务端和客户端可以用不同的语言来开发。只需要依照 IDL(Interface Description Language)定义一次接口,Thrift 工具就能自动生成 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等语言的代码。

# 安装

Thrift 的安装还是有些繁琐的,跟着官方文档的走就可以。如果你是 Mac OS X, 这里有更方便的方法。

brew install boost
brew install libevent
brew install thrift
gem install thrift -- --with-cppflags='-D_FORTIFY_SOURCE=0'

不过注意上述方法默认安装的最新版。

# Thrift 类型系统

thrfit 的类型系统包括了基本类型,比如 bool, byte, double, string 和 int。也提供了特殊类型如 binary,提供了 structs(等同于无继承的 class),还提供了容器类型(list,set,map)。

# 基本类型 (basic types)

  • bool: 布尔变量
  • byte: 8 位有符号整数
  • i16: 16 位有符号整数
  • i32: 32 位有符号整数
  • i64: 64 位有符号整数
  • double: 64 位浮点数
  • string: 字符串

注:thrift 不支持无符号整数类型,因为很多编程语言不存在无符号类型,比如 java

# 特殊类型 (special types)

binary: 未编码的字节序列

# 枚举 (enum)

枚举的定义形式和 Java 的 Enum 定义差不多,例如:

enum Sex {
    MALE,
    FEMALE
}

# 容器类型 (container)

集合中的元素可以是除了 service 之外的任何类型,包括 exception。

  • list: 一系列由 T 类型的数据组成的有序列表,元素可以重复
  • set: 一系列由 T 类型的数据组成的无序集合,元素不可重复
  • map: 一个字典结构,key 为 K 类型,value 为 V 类型

# 结构体 (struct)

结构体中包含一系列的强类型域,等同于无继承的 class。可以看出 struct 写法很类似 C 语言的结构体。

struct Example {
  1:i32 number=10,
  2:i64 bigNumber,
  3:list<double> decimals,
  4:string name="thrifty"
}

# 可选与必选

thrift 提供两个关键字 requiredoptional ,分别用于表示对应的字段时必填的还是可选的。例如:

struct People {
    1: required string name;
    2: optional i32 age;
}

表示 name 是必填的,age 是可选的。

# 联合 (union)

当一个结构体中,field 之间的关系是互斥的,即只能有一个 field 被使用被赋值。我们可以用 union 来声明这个结构体,而不是一堆堆 optional 的 field,语意上也更明确了。例如:

union JavaObjectArg {
  1: i32 int_arg;
  2: i64 long_arg;
  3: string string_arg;
  4: bool bool_arg;
  5: binary binary_arg;
  6: double double_arg;
}

# 异常 (Exceptions)

可以自定义异常类型,所定义的异常会继承对应语言的异常基类,例如 java,就会继承 java.lang.Exception

exception InvalidOperation {
  1: i32 what,
  2: string why
}

# 服务 (service)

thrift 定义服务相当于 Java 中创建 Interface 一样,创建的 service 经过代码生成命令之后就会生成客户端和服务端的框架代码。定义形式如下:

service StringCache {
  void set(1:i32 key, 2:string value),
  string get(1:i32 key) throws (1:KeyNotFound knf),
  void delete(1:i32 key)
}

# 命名空间 (namespace)

thrift 的命名空间相当于 Java 中的 package 的意思,主要目的是组织代码。thrift 使用关键字 namespace 定义命名空间,例如:

namespace java me.wuchong.thrift

注意末尾不能有分号,由此生成的代码,其包路径结构为 me.wuchong.thrift

下一篇文章,将通过一个简单的实例来了解 thrift 的使用。

# 参考资料

  • Thrift: The Missing Guide
  • Thrift Tutorial
  • thrift 入门教程