0 本文目的
本文简单介绍thrift概念和基础用法,为想简单了解的人提供一个快速的入门,决定是否要使用以及基础的使用方式。同时,对于有在使用的人(比如我自己),提供一个快速的基础的回顾。
本文使用的thrift版本为0.5。
1 为什么要使用thrift
1.1 应用场景在哪儿
thrift 可以用来实现跨语言的rpc调用,让我们像使用本地接口一样地去使用远程接口。这样的rpc服务调用也是微服务架构的最基础的部分。由facebook最早开源出来,比较成熟。
1.2 其他方案比较
- http rest实际上也可以作为跨语言的远程调用。一般来说是文本形式的数据交换,当然也可以自己定义二进制形式的,不过这样一来相当于自己定义了rpc框架。另外协议当然是使用的http了。
- thrift可以有多种protocol和transport供选择,一般来说使用二进制,基于tcp socket,更加高效。
- gRPC是由谷歌开源,较thrift来说更晚开源,目前来看在协议丰富度和语言丰富度上不及thrift,在带宽敏感时相对表现更好。
1.3 不支持什么
- 不能返回null
- 不支持继承,多态
2 thrift 基本概念
2.1 层级
层级 | 组件 |
---|---|
Server | single-threaded, event-driven etc |
Processor | compiler generated |
Protocol | JSON, compact etc |
Transport | raw TCP, HTTP etc |
2.2 Server
类 | 描述 |
---|---|
TSimplerServer | 接受一个连接,处理连接请求,直到客户端关闭了连接,它才回去接受一个新的连接。 |
TNonblockingServer | 使用非阻塞的I/O解决了TSimpleServer一个客户端阻塞其他所有客户端的问题。 |
THsHaServer | (半同步/半异步的server)它使用一个单独的线程来处理网络I/O,一个独立的worker线程池来处理消息。这样,只要有空闲的worker线程,消息就会被立即处理,因此多条消息能被并行处理。 |
TThreadPoolServer | 有一个专用的线程用来接受连接。一旦接受了一个连接,它就会被放入ThreadPoolExecutor中的一个worker线程里处理。 |
2.3 Processor
自己实现的处理逻辑
2.4 Protocol
类 | 描述 |
---|---|
TBinaryProtocol | 二进制格式 |
TCompactProtocol | 高效和压缩的二进制格式 |
TDenseProtocoal | 与TCompactProtocol相比,meta信息略有不同 |
TJSONProtocoal | JSON |
TDebugProtocoal | text 格式 方便调试 |
2.5 Transport
TTransport主要处理服务器端和客户端的网络读写。主要的接口
- open
- close
- read
- write
- flush
例如常用的客户端是TSocket就是TTransport的一个实现
在服务器端当有请求来的时候,通过TServerTransport可以创建TTransport对象,然后通过TTransport发送数据给客户端,主要的接口
- open
- listen
- accept
- close
例如TNonblockingTransport,TSocket等。ServerTransport可以理解为主要实现了accept以后要做的事情,到底是采用何种方式(同步异步,阻塞非阻塞)把请求交给processor处理。
3 简单应用
3.1 idl
官方文档可以参考link.
常用的几个点:
- 文件是 .thrift 结尾 ,里面可以定义多个类,枚举
- namespace *****
- include “xxx.thrift”
- 定义model 类:
一般来讲我们都用optional, 避免用required,以免后续有更新的时候遇到兼容问题struct AModel { 1: optional i64 id; // 注释 }
- 定义枚举:
enum TAttribute { BASIC = 1; // 基本属性 DATETIME = 2; // 日期属性 }
- 定义服务
service BService extends A.AService { A.AModel getA(1: A.AModel model); BModel getB(1: BModel model, 2: string name); }
例子:
- model
namespace java com.tx.thrift.model
enum TGreetingType {
EAT = 1; // 问候吃饭
MORNING = 2; // 早
}
struct TGreeting {
1: optional string name; // 名字
2: optional TGreetingType greetingType; // 寒暄类型
}
- service, 引用model
namespace java com.tx.thrift.service
include "hello_model.thrift"
service HelloService {
string hello(1: hello_model.TGreeting greeting);
}
3.2 生成接口
对于java,可以使用maven-thrift-plugin插件,配置后可以在编译时生成代码jar包,在server端和client分别引用。
<plugin>
<groupId>org.apache.thrift.tools</groupId>
<artifactId>maven-thrift-plugin</artifactId>
<version>0.1.15-mdt0.0.2</version>
<configuration>
<thriftExecutable>thrift</thriftExecutable>
<generator>java</generator>
<compilerVersion>0.5.0</compilerVersion>
</configuration>
<executions>
<execution