Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架
Posted 三丰SanFeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架相关的知识,希望对你有一定的参考价值。
本文首先介绍了什么是Apache Thrift,接着介绍了Thrift的安装部署及如何利用Thrift来实现一个简单的RPC应用,并简单的探究了一下Thrift的内部实现原理,最后给出一个基于Thrift的可扩展的分布式RPC调用框架,在中小型项目中是一个常见的SOA实践。
Thrift介绍
Apache Thrift是Facebook 开发的远程服务调用框架,它采用接口描述语言(IDL)定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++, Java, Python, php, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等创建高效的、无缝的服务,其传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。本文将详细介绍 Thrift 的使用,并简要分析Thrift的底层运行原理,最后给出一个基于Thrift的可扩展分布式RPC框架。
Thrift安装部署
首先安装make tools和bison
yum -y install automake gcc gcc-c++
wget http://ftp.gnu.org/gnu/bison/bison-2.5.1.tar.gz
tar -zxvf bison-2.5.1.tar.gz
cd bison-2.5.1
./configure --prefix=/usr/local/
make;make install
然后安装thrift底层依赖库和boost
yum -y install libevent2-devel zlib-devel openssl-devel
wget http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.tar.gz
tar -zxvf boost_1_55_0.tar.gz
cd boost_1_55_0
./bootstrap.sh
./b2 install
安装Thrift
Wget http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.3/thrift-0.9.3.tar.gz
cd thrift-0.9.3
./configure;make;make install
Thrift cpp源码类介绍
Thrift代码包(位于thrift-0.9.3/lib/cpp/src)有以下几个目录:
concurrency:并发和时钟管理方面的库
processor:Processor相关类
protocol:Protocal相关类
transport:transport相关类
server:server相关类
async:异步rpc相关类
Thrift实现实例
这里介绍一个简单的 Thrift 实现实例,使读者能够快速直观地了解什么是 Thrift 以及如何使用 Thrift 构建服务。
创建一个简单的服务Log。
首先根据 Thrift 的语法规范编写脚本文件 log.thrift,代码如下:
struct LogInfo { 1: required string name, 2: optional string content, } service LogSender { void SendLog(1:list<LogInfo> loglist); string GetLog(1:string logname); }
其中定义了服务 Log 的两个方法,每个方法包含一个方法名,参数列表和返回类型。每个参数包括参数序号,参数类型以及参数名。 Thrift 是对 IDL(Interface Definition Language) 描述性语言的一种具体实现。因此,以上的服务描述文件使用 IDL 语法编写。使用 Thrift 工具编译 log.thrift,就会生成相应的 LogSender.cpp 文件。该文件包含了在 log.thrift 文件中描述的服务Log的接口定义以及服务调用的底层通信细节,用于构建客户端和服务器端的功能。
调用thrift命令生成代码,命令为thrift --gen <language> <Thrift filename>
[[email protected] log_thrift]# thrift -gen cpp log.thrift
[[email protected] log_thrift]# tree gen-cpp/
gen-cpp/
├── log_constants.cpp
├── log_constants.h
├── LogSender.cpp
├── LogSender.h
├── LogSender_server.skeleton.cpp
├── log_types.cpp
└── log_types.h
Thrift文件与生成的代码对应关系
每个thrift文件会产生四个文件,分别为:${thrift_name}_constants.h,${thrift_name}_constants.cpp,${thrift_name}_types.h,${thrift_name}_types.cpp,
对于含有service的thrift文件,会额外生成两个文件,分别为:${service_name}.h,${service_name}.cpp
对于含有service的thrift文件,会生成一个可用的server桩:${service_name}_server.skeleton.cpp
一个阻塞式服务器实现server.cpp
#include "gen-cpp/LogSender.h" #include <map> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/server/TSimpleServer.h> #include <thrift/transport/TServerSocket.h> #include <thrift/transport/TBufferTransports.h> using namespace ::apache::thrift; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; using namespace ::apache::thrift::server; using boost::shared_ptr; std::map<std::string, std::string> logMap; class LogSenderHandler : virtual public LogSenderIf { public: LogSenderHandler() { // Your initialization goes here } void SendLog(const std::vector<LogInfo> & loglist) { // Your implementation goes here sleep(5); time_t now = time(NULL); printf("SendLog, now = %s\n", ctime(&now)); for (size_t i = 0; i < loglist.size(); ++i) { if (logMap.find(loglist[i].name) == logMap.end()) { printf("name=[%s], content=[%s]\n", loglist[i].name.c_str(), loglist[i].content.c_str()); logMap.insert(std::make_pair(loglist[i].name, loglist[i].content)); } } } void GetLog(std::string& _return, const std::string& logname) { // Your implementation goes here std::map<std::string,std::string>::iterator iter = logMap.find(logname); if (iter != logMap.end()) { _return = iter->second; } else { _return = "Not Found!"; } } }; int main(int argc, char **argv) { int port = 9090; shared_ptr<LogSenderHandler> handler(new LogSenderHandler()); shared_ptr<TProcessor> processor(new LogSenderProcessor(handler)); shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); server.serve(); return 0; }
阻塞式服务器对应客户端实现client.cpp
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h>以上是关于Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架的主要内容,如果未能解决你的问题,请参考以下文章