一、简介
thrift来自于facebook,是一个软件框架,用来进行可扩展且跨语言的服务的开发。允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。它可支持 C++、
Java,、Python,、PHP、C#等等一些主流的语言,类似于Google的protobuf,关于两者之间的比较网上也有很多,还有一个后起之秀avro有hadoop的背景,也值得关注。由于我最早接触的是thrift,因此一直都在使用这个,而且已在几个项目中使用了,没出现过什么问题,因此也没心思去研究protobuf和avro了。
二、下载与安装
环境:Ubuntu
依赖:boost、libevent
下载地址:http://thrift.apache.org/download/
下载文件:thrift-0.9.0.tar.gz
我用的是Ubuntu,按照官网给出的安装步骤安装没什么问题,主要是要依赖boost和libevent,把这两个装好就可以。可直接使用官网给的命令:
sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev
由于我常用boost开发,已经安装过了boost,因此直接连接过去就可以。
$>tar xvf thrift-0.9.0.tar.gz $>ch thrift-0.9.0 $>./config --prefix=/usr/local/thrift --with-boost=/usr/local/boost $>make $>make install
三、测试
直接使用官网的例子
1.编写代码生成脚本文件
UserStorage.thrift(注:后缀必须是thrift,文件名会生成类名)
struct UserProfile { 1: i32 uid, 2: string name, 3: string blurb } service UserStorage { void store(1: UserProfile user), UserProfile retrieve(1: i32 uid) }
要将$THRIFT_HOME/bin加入环境变量的PATH中,然后执行命令:
$>thrift -gen cpp UserStorage.thrift
这是当前目录下会有个gen-cpp的目录,里面包含了生成的相关C++代码(也可以通过thrift命令生成其它代码,如:thrift -gen java UserStorage.thrift ,这样就生成了java代码):
UserStorage.h
UserStorage.cpp
UserStorage_types.h
UserStorage_types.cpp
UserStorage_constants.h
UserStorage_constants.cpp
UserStorage_server.skeleton.cpp
上面标红的文件是我们这个例子所需的代码,另外三个可暂时不用管。
2.编写服务器端代码
server.cpp
#include <iostream> #include <boost/shared_ptr.hpp> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/transport/TBufferTransports.h> #include <thrift/transport/TServerSocket.h> #include <thrift/server/TSimpleServer.h> #include "UserStorage.h" using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::server; using namespace apache::thrift::concurrency; using namespace boost; class UserStorageHandler : virtual public UserStorageIf { public: UserStorageHandler() { // Your initialization goes here } void store(const UserProfile& user) { // Your implementation goes here printf("store\n"); } void retrieve(UserProfile& _return, const int32_t uid) { // Your implementation goes here printf("retrieve\n"); } }; int main(int argc, char **argv) { int port = 9090; shared_ptr handler(new UserStorageHandler()); shared_ptr processor(new UserStorageProcessor(handler)); shared_ptr serverTransport(new TServerSocket(port)); shared_ptr transportFactory(new TBufferedTransportFactory()); shared_ptr protocolFactory(new TBinaryProtocolFactory()); TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); server.serve(); return 0; }
g++ -o server -I/usr/local/boost/include -I/usr/local/thrift/include -L/usr/local/boost/lib -L/usr/local/thrift/lib -lthrift -lthriftnb -levent server.cpp
3.客户端代码
client.cpp
#include <iostream> #include <boost/shared_ptr.hpp> #include <thrift/transport/TSocket.h> #include <thrift/transport/TBufferTransports.h> #include <thrift/protocol/TProtocol.h> #include <thrift/protocol/TBinaryProtocol.h> #include "UserStorage.h" using namespace apache::thrift; using namespace apache::thrift::transport; using namespace apache::thrift::protocol; using namespace boost; int main() { boost::shared_ptr<TTransport> m_sock; boost::shared_ptr<TTransport> m_pTransport; boost::shared_ptr<TProtocol> m_protocol; shared_ptr<UserStorageClient> m_pClient; m_sock.reset(new TSocket("127.0.0.1", 9090)); m_pTransport.reset(new TFramedTransport(m_sock)); m_protocol.reset(new TBinaryProtocol(m_pTransport)); m_pClient.reset(new UserStorageClient(m_protocol)); m_pTransport->open(); UserProfile up; up.uid = 1; up.name = "bocheng"; up.blurb = "1"; m_pClient->store(up); return 0; }
g++ -o client -I/usr/local/boost/include -I/usr/local/thrift/include -L/usr/local/boost/lib
-L/usr/local/thrift/lib -lthrift -lthriftnb -levent client.cpp
这只是一个比较简单的例子,服务器是用的是TSimpleServer,是阻塞单线程的服务器,一般在线上跑的不会用到这个服务器,因此后续篇会介绍如何使用TNonblockingServer编写非阻塞多线程的服务器。