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 过程
- 下载并编译 thrift编译器 .
- 编写thrift文件.需要用到 thrift自定义数据类型 .包括
- 基本数据类型
- 特殊数据类型(binary)
- 结构体
- 容器(list,set,map).容器元素可以是服务以外的任何thrift type .
- 异常(Exceptions)
- 服务
- 编译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 } }; |
3 Apache Thrift 架构
Thrift 是一套完整的C/S体系架构,是IDL的一个具体实现。Thrift自己定义了传输协议规范(TProtocol)和传输数据标准(TTransports),使用IDL描述需要传输的数据结构和逻辑,然后根据不同的平台生成相应的代码。并通过序列化和压缩数据来降低数据交互的成本。
如下图所示:
从上到下分别为这几个部分:
- 业务逻辑实现
- TProcessor x客户端/服务端对应的Service与序列化/反序列化组件
- TPortocol 协议
- TTransport 传输体系
- I/O 底层通信
其中 2 是由IDL编译的代码构成, 1 则需要根据业务逻辑具体实现。
3.1 Server 服务端
常见的服务端类型有以下几种:
- TSimpleServer. 单线程服务端.使用标准的阻塞式I/O
- TThreadedServer. 多线程服务端,使用阻塞式IO,每个请求创建一个线程,效率高,但资源占用多。
- TThreadPoolServer. 线程池服务端. 使用标准的阻塞式I/O
- TNonblockingServer. 多纯种服务端. 非阻塞式I/O(需要配合TFramedTransport使用).能够使用少量线程处理大量并发,但延迟较高。
3.2 TProtocol 协议层
网络传输协议大体上可分为文本传输与二进制流传输。文本传输易读,而二进制流传输通常情况下体积更小,可以提高传输效率。Thrift可以让用户根据实际需求选择传输协议的类别。
Thrift的传输协议以 TVirtualProtocol 为基类,分以下几种:
- TBinaryProtocol. 以二进制进行传输
- TJsonProtocol. 以Json协议进行传输
- TCompactProcotol. 以高效密集的二进制格式进行传输
- TDebugProtocol. 携带详细信息的文本格式,便于调试
- TSimpleJsonProtocol. 以只写Json协议进行传输(仅在Java中有实现)
3.3 TTransport 传输层
Thrift传输方式以 TVirtualTransport 为基类,常用的传输方式有以下几种:
- TSocket. 采用 TCPsocket ,以阻塞式I/O进行传输
- THttpTransport. (THttpClient/THttpServer)采用Http传输协议进行数据传输。
- TFileTransport. 以文件方式进行传输。
- TZlibTransport. 以压缩数据进行传输。(需要libzip支持)
thrift还提供以下类对上面的几个类进行装饰,以提高传输效率:
- TFramedTransport. 以非阻塞方式,按块大小进行传输.(Java中的NIO?)
- TBufferedTransport. 对传输对象进行缓存。
- 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 选项去掉该语言的支持。
编译时需要的依赖项较多,需要及时关注错误提示信息并处理。