Apache Thrift

目录

1 简介

1.1 概览

Apache Thrift官网
Thrift是一个跨语言的服务开发部署 框架,其最初由Facebook于2007年开发,于2008年加入Apache开源项目。
Thrift 通过编译thrift文件(由Thrift Types 组织的中间语言,用于定义RPC数据结构),生成不同语言的类。这些类负责RPC协议层和传输层的实现。

1.2 优点

相对于XML、Json,Thrift在性能和传输数据压缩上有绝对优势。

2 简单使用

2.1 过程

  1. 下载并编译 thrift编译器 .

  2. 编写thrift文件.需要用到 thrift自定义数据类型 .包括

  3. 基本数据类型

  4. 特殊数据类型(binary)

  5. 结构体

  6. 容器(list,set,map).容器元素可以是服务以外的任何thrift type .

  7. 异常(Exceptions)

  8. 服务

  9. 编译thrift文件,生成可供服务端和客户调用的源码.命令语法如下:

1
thrift --gen <language> <thrift filename>

2.2 简单实例

2.2.1 编辑thrift文件

代码清单如下:

1
2
3
4
5
6
7
8
9
10
11
12
namespace cpp im
struct Msg
{
1:i32 idFrom,
2:i32 idTo,
3:string content,
}

service transMsg
{
void trans(1:Msg m);
}

2.2.2 生成cpp代码

使用thrift.exe :

1
thrift.exe -gen cpp transMsg.thrift

此时会在 “gen-cpp” 文件夹(默认文件夹)下生成相应的cpp代码:

1
2
3
4
5
6
7
msg_constants.cpp
msg_constants.h
msg_types.cpp
msg_types.h
transMsg.cpp
transMsg.h
transMsg_server.skeleton.cpp

其中 “msg_ types” 和 “msg_ constants” 对数据类型进行了定义,“transMsg” 实现了基本逻辑。“transMsg_ server.skeleton” 则简单实现了一个server端的实例。

2.2.3 实现业务逻辑

新建两个工程,一个做为服务端,一个做为用户端。 将 gen-cpp 文件夹下的文件分别添加到两个工程中,并在工程中添加thrift的静态库(或直接引用源码).
Server端的工程可以直接使用生成的代码。Client端的业务则需要自己实现。
下面简单实现Client端的业务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int main(int argc, char **argv) {
int port = 9090;
std::string strHost("192.168.3.11");

boost::shared_ptr<TTransport> socket(new TSocket(strHost.c_str(), port));
boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
transMsgClient client(protocol);

try
{
im::Msg m;
m.__set_idFrom(10);
m.__set_idTo(280);
m.__set_content("Hi, I`m a message. ");

transport->open();

client.trans(m);

transport->close();
}
catch (TException e)
{
printf("%s", e.what());
}

system("pause");
return 0;
}

其中strHost为服务器的IP.

简单更改Server端的业务逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
class transMsgHandler : virtual public transMsgIf {
public:
transMsgHandler() {
// Your initialization goes here
}

void trans(const Msg& m) {
// Your implementation goes here
printf("trans\n");
printf(" [%d] Saied To [%d]: %s\n", m.idFrom, m.idTo, m.content.c_str()); //The Logic we add here
}
};

2.2.4 测试实例

先在PC 192.168.3.11 上启动服务端程序,然后启动客户端程序。测试服务端可以收到数据并能正确解析:

[

sampleResult

](https://code.wandoer.com/wp-content/uploads/2016/05/sampleResult.png)

3 Apache Thrift 架构

Thrift 是一套完整的C/S体系架构,是IDL的一个具体实现。Thrift自己定义了传输协议规范(TProtocol)和传输数据标准(TTransports),使用IDL描述需要传输的数据结构和逻辑,然后根据不同的平台生成相应的代码。并通过序列化和压缩数据来降低数据交互的成本。
如下图所示:

[

thriftframe

](https://code.wandoer.com/wp-content/uploads/2016/05/thriftframe.png)

从上到下分别为这几个部分:

  1. 业务逻辑实现

  2. TProcessor x客户端/服务端对应的Service与序列化/反序列化组件

  3. TPortocol 协议

  4. TTransport 传输体系

  5. I/O 底层通信

其中 2 是由IDL编译的代码构成, 1 则需要根据业务逻辑具体实现。

3.1 Server 服务端

常见的服务端类型有以下几种:

  1. TSimpleServer. 单线程服务端.使用标准的阻塞式I/O

  2. TThreadedServer. 多线程服务端,使用阻塞式IO,每个请求创建一个线程,效率高,但资源占用多。

  3. TThreadPoolServer. 线程池服务端. 使用标准的阻塞式I/O

  4. TNonblockingServer. 多纯种服务端. 非阻塞式I/O(需要配合TFramedTransport使用).能够使用少量线程处理大量并发,但延迟较高。

3.2 TProtocol 协议层

网络传输协议大体上可分为文本传输与二进制流传输。文本传输易读,而二进制流传输通常情况下体积更小,可以提高传输效率。Thrift可以让用户根据实际需求选择传输协议的类别。
Thrift的传输协议以 TVirtualProtocol 为基类,分以下几种:

  1. TBinaryProtocol. 以二进制进行传输

  2. TJsonProtocol. 以Json协议进行传输

  3. TCompactProcotol. 以高效密集的二进制格式进行传输

  4. TDebugProtocol. 携带详细信息的文本格式,便于调试

  5. TSimpleJsonProtocol. 以只写Json协议进行传输(仅在Java中有实现)

3.3 TTransport 传输层

Thrift传输方式以 TVirtualTransport 为基类,常用的传输方式有以下几种:

  1. TSocket. 采用 TCPsocket ,以阻塞式I/O进行传输

  2. THttpTransport. (THttpClient/THttpServer)采用Http传输协议进行数据传输。

  3. TFileTransport. 以文件方式进行传输。

  4. TZlibTransport. 以压缩数据进行传输。(需要libzip支持)

thrift还提供以下类对上面的几个类进行装饰,以提高传输效率:

  1. TFramedTransport. 以非阻塞方式,按块大小进行传输.(Java中的NIO?)

  2. TBufferedTransport. 对传输对象进行缓存。

  3. TMemortBuffer. 从缓存中读写数据

4 附

4.1 安装Thrift

下载源码
1
git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift
编译
1
2
3
4
cd thrift
./bootstrap.sh
./configure --without-csharp --without-erlang
make

编译与运行需要 libevent\openSSL\boost 等库的支持。
如果不需要支持某些语言的,可以使用 –without-xx 选项去掉该语言的支持。
编译时需要的依赖项较多,需要及时关注错误提示信息并处理。

5 参考资料

  1. thrift.apache.org

  2. Thrift: The Missing Guide

  3. IBM developerWorks: Apache Thrift - 可伸缩的跨语言服务开发框架

  4. 董的博客:Thrift使用指南

  5. wikipedia: Apache Thrift