Thrift 是什么
The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.
from : http://thrift.apache.org/
翻译:
Apache Thrift 是一个可扩展的用来实现跨语言服务的开发框架。
它组合一个代码生成引擎和一个软件栈来创建下面各种语言 (C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi 。。。 )之间的高效无缝的服务。
Thrift 的安装
环境 : OpenSUSE , 64bit
参见:
- 下载源码zip并解压。
- 于Thrift根目录执行
./configure
- 于Thrift根目录执行
./make
期间遇到提示某库(比如 libevent) 没有装好, 就使用zypper(类似Ubuntu 的apt-get) 默认安装 .
在编译test的时候遇到Makefile的问题, gen-cpp 内头文件无法include, 就是用thrift 命令手动生成之( 或者先删除对应Makefile命令 , 木有关系) 。
Thrift 的基本概念
参见
软件栈概念图:
+-------------------------------------------+
| Server |
| (single-threaded, event-driven etc) |
+-------------------------------------------+
| Processor |
| (compiler generated) |
+-------------------------------------------+
| Protocol |
| (JSON, compact etc) |
+-------------------------------------------+
| Transport |
| (raw TCP, HTTP etc) |
+-------------------------------------------+
实际是Thrift 是采用RPC(远程调用) 的概念实现跨语言的, Transport层负责使用指定协议(TCP / HTTP / FILE / PIPE … ) 交换数据, Protocol 层负责用指定的协议( JSON ,Binary , XML … ) 编解码数据, Processor 层是我们自己code的层, 负责 接口的具体实现( server端 ) / 对接口的调用使用 ( client 端) 。 Server 层实际是是对下面3层的整合, 当 client 连接到server调用某个接口的时候, Processor 按照接口规定准备数据, Protocol 按照配置编码数据, 通过Transport 层按照指定的协议发送数据, server 通过Transport收到数据后, Protocol 解码数据, Processor 层使用数据真正的调用接口,完成逻辑, 如果有返回值的话, 再按照相反的流程传回client 。 见下图 :
使用Thrift 写HelloWorld
Thrift 除了 Processor 的实现和server的配置之外, 其他的代码都会给自动生。
首先, 我们要定义接口 , 使用 Thrift 定义的自己的IDL ( interface description language ) ,
hello.thrift
service Hello {
string getString()
}
我的服务器端使用C++ , 所以先生成对应的C++代码 :
thrift --gen cpp hello.thrift
自动生成gen-cpp 文件夹, 打开里面的hello.h 头文件, 找到下面的接口 :
class HelloIf {
public:
virtual ~HelloIf() {}
virtual void getString(std::string& _return) = 0;
};
为服务器接口添加实现代码 helloServer.cpp ( 由生成的 Hello_server.skeleton.cpp 修改成):
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/PosixThreadFactory.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/TToString.h>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include "gen-cpp/Hello.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::concurrency;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
class HelloHandler : public HelloIf
{
public:
virtual void getString(string& _return) {
_return = "Hello World\n";
}
};
int main(int argc, char **argv)
{
boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
boost::shared_ptr<HelloHandler> handler(new HelloHandler());
boost::shared_ptr<TProcessor> processor(new HelloProcessor(handler));
boost::shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));
boost::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
TSimpleServer server(processor,
serverTransport,
transportFactory,
protocolFactory);
cout << "Starting the server..." << endl;
server.serve();
cout << "Done." << endl;
return 0;
}
客户端也C++语言 ( 好吧我最熟悉这个)
#include <iostream>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include "gen-cpp/Hello.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
int main(int argc, char** argv) {
boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
HelloClient client(protocol);
transport->open();
string hello;
client.getString(hello);
cout<<hello;
transport->close();
}
Cmake 维护工程 :
cmake_minimum_required(VERSION 3.0)
PROJECT (helloWord)
INCLUDE_DIRECTORIES(./gen-cpp)
SET( SERVER_FILES helloServer.cpp)
SET( LIB_SOURCE ./gen-cpp/Hello.cpp ./gen-cpp/hello_constants.cpp ./gen-cpp/hello_types.cpp )
ADD_EXECUTABLE(server ${SERVER_FILES} ${LIB_SOURCE} )
TARGET_LINK_LIBRARIES(server -lthrift)
编译 :
mkdir build
cd build
cmake ,,
make
先启动server , 然后启动client 输出 :
Hello World