Thrift 学习笔记
1. Thrift 简介
Thrift 是有 Facebook 开源的一套 RPC 框架, 支持多种语言,它是通过自身的 中间语言(IDL),并借助代码生成引擎来生成各种主流语言的代码模板
2. IDL 语言
Thrift 采用 IDL(Interface Definition Language)来定义通用的服务接口,然后通过 Thrift 提供的编译器,可以将服务接口编译成不同语言编写的代码,通过这个方式来实现跨语言的功能。
IDL 中有基本类型、结构体类型、容器类型、枚举类型、异常类型、服务类型等六种类型。熟悉了这些常用类型后基本上可以应付日常开发。
2.1 基本类型:
bool: 布尔值
byte: 8 位有符号整数
i16: 16 位有符号整数
i32: 32 位有符号整数
i64: 64 位有符号整数
double: 64 位浮点数
string: UTF-8 编码的字符串
binary: 二进制串
2.2 struct(结构体):
类似于 C 语言中的结构体。在 Java 中就是 POJO,struct 类型有以下几个要求:
struct 不能继承,但是可以嵌套,不能嵌套自己。
其成员都是有明确类型
成员是被正整数编号过的,其中的编号使不能重复的,这个是为了在传输过程中编码使用。
成员分割符可以是逗号(,)或是分号(;),而且可以混用
字段会有 optional 和 required 之分和 protobuf 一样,但是如果不指定则为无类型–可以不填充该值,但是在序列化传输的时候也会序列化进去,optional 是不填充则部序列化,required 是必须填充也必须序列化。
每个字段可以设置默认值
同一文件可以定义多个 struct,也可以定义在不同的文件,进行 include 引入。
例如:
2.3 Container (容器)
list<t>: 元素类型为 t 的有序表,容许元素重复。对应 Java 的 ArrayList
set<t>: 元素类型为 t 的无序表,不容许元素重复。对应 Java 的 HashSet
map<t, t>: 键类型为 t,值类型为 t 的 kv 对,键不容许重复。对应 Java 的 HashMap
例如:
2.4 enum (枚举):
Thrift 不支持枚举类嵌套,枚举常量必须是 32 位的正整数。
例如:
2.5 Exception (异常):
异常在语法和功能上类似于结构体,不过使用的关键字是 exception。对应 Java 的 Exception
例如:
2.6 Service (服务定义类型):
即我们需要提供的服务接口。
例如:
2.7 常量类型
在 Java 中我们可能还会经常用到常量类型,在 IDL 中 常亮类型可以使用 const 关键字。
例如:
2.8 Namespace (名字空间)
IDL 中的命名空间即是 Java 中的包名
例如:
2.9 注释
IDL 支持 单行注释和多行注释
2.10 Include(导入)
类似于 Java 中的 import 在本文件中引入其他文件中定义的内容。
**注意:**thrift 文件名要用双引号包含,末尾没有逗号或者分号。
例如:
3. Java 版的 Hello World
3.1 安装
由于 Thrift 需要使用代码生成引擎来将 Thrift 代码转换成其他语言(Java)的代码,所以需要在本地安装一下 Thrift
注意:本地安装的 Thrift 版本最好和生产环境保持一致。不然很可能会出现一些问题
使用以下命令安装:
本人使用的是 Mac OS ,你和可以去 Thrift 官网,下载对应的安装包进行安装。
最终,如果你在命令行下执行下面的命令,出现 Thrift 版本号,就说明安装成功了。
IDEA 默认是不支持 Thrift 所以需要安装 Thrift Support
插件。
3.2 配置
安装好插件,重启后就能在 File -> new -> Project...
菜单下 看到 Thrift 工程了。
创建完成 Thrift 项目后,还需要配置一下 Thrift 代码生成引擎相关的东西。
打开菜单 File - > Project Structure... -> Project Settings -> Facets
,选择 Thrift
然后会让你代码输出的位置。
3.3 创建 Thrift 文件
新建 HelloService.thrift
,在菜单中可能找不到创建 thrift 文件的菜单,直接新建 File 然后以 thrift 作为文件后缀就可以。
内容如下:
在这个接口文件中我们定义了一个 sayHello 的接口,它接收一个 String 类型的参数,并返回一个 String 类型的值。
现在我需要编译该 thrift 文件,然后就会自动生成我们需要的代码。
我们可以直接在控制台执行以下命令。
然后就能在gen-java
目录中看到生成后的 java 文件了。
还有一种办法,就是将 thrift 编译器添加到右键菜单里,直接在 IDEA 里编译。
打开 Preferences...
菜单,设置好你的 Thrift 的安装目录,然后勾选上下面的这个选项,就可以在 IDEA 里直接编译 thrift 文件了。
注意:thrift 文件 必须要在 src 目录下,或者手动设置的 source 目录(IDEA 显示蓝色的文件夹)下才会有 Recompile 菜单
PS: 搞了半天,最后可以编译了,结果报错:
也不知道是 IDEA 的问题,还是插件的问题,网上搜了一下啊,貌似没有遇到这个问题的,有时间再研究吧,直接在控制台编译好,然后我们再新建一个 Maven 项目。并添加 thrift 依赖
然后把上面生成的 java 文件复制到 对应的包下面。
然后我再创建一个实现类ThriftHelloServiceImpl.java
,来实现我们定义好的接口。内容如下:
3.4 创建服务端和客户端类
我们这里采用 Main 方法的形式来进行客户端与服务端的通信,即启动两个 Main 方法,分别表示服务端与客户端。
首先创建服务端的 Main 方法,代码如下:
然后再创建客户端的 Main 方法,代码如下:
然后启动服务端的 Main 方法,再启动客户端的 Main 方法,会看到 hello thrift-1,说明 RPC 通信成功了。
4. 关于 Thrift 生成好的 Java 代码
可能你会很奇怪,我们仅仅在 .thrift 文件中定义了一个接口,但是在生成后的 .java 文件中,却生成了大量的代码。
其实我们没必要太过关注生成后的代码,主要关注下面几个东西就可以了。
服务端关注以下两个接口类:
ThriftHelloService.Iface
这个是服务端提供同步调用的接口。就是说,你实现的这个接口下面的方法,都会采用同步的方式调用。
ThriftHelloService.AsyncIface
同样,如果客户端和服务端需要采用异步的方式通信,服务端就需要实现 AsyncIface 下的接口。
同样,消费端也有两个 Client 一个是同步调用的,一个是异步调用的。
ThriftHelloService.Client 执行同步调用。
ThriftHelloService.AsyncClient 执行异步调用。
版权声明: 本文为 InfoQ 作者【U+2647】的原创文章。
原文链接:【http://xie.infoq.cn/article/6490e15c2bc84e14c11c847cf】。文章转载请联系作者。
评论