现在的位置: 首页 > 综合 > 正文

利用thrift在c++、java和python之间相互调用

2013年12月13日 ⁄ 综合 ⁄ 共 6145字 ⁄ 字号 评论关闭

        thrift做为跨语言调用的方案有高效,支持语言较多,成熟等优点;代码侵入较强是其弱点。 
        下面记录以C++做服务器,C++,java和python做客户端的示例,这个和本人现在工作环境吻合,使用多线程长连接的socket来建立高效分布式系统的跨语言调用平台。 

        遗憾的是目前版本(0.7.0)的C语言还不支持Compact协议,导致在现在的环境中nginx c module调用thrift要使用binary协议。thrift开发团队似乎对C语言不太感冒。 

1.定义idl文件acsuser.thrift 

struct User{  
 1: string uid,  
 2: string uname,  
 3: bool usex,  
 4: i16 uage,  
}  
service UserService{  
 void add(1: User u),  
 User get(1: string uid),  
}  

2.生成c++,java和python代码框架 

thrift -r --gen cpp acsuser.thrift   
thrift -r --gen java acsuser.thrift   
thrift -r --gen py acsuser.thrift  

这时生成子目录gen-cpp,gen-java,gen-py 
3.生成C++服务端代码

cp gen-cpp/UserService_server.skeleton.cpp UserServer.cpp 

修改UserServer.cpp 

#include "UserService.h"  
#include <config.h>  
//#include <protocol/TBinaryProtocol.h>  
#include <protocol/TCompactProtocol.h>  
#include <server/TSimpleServer.h>  
#include <transport/TServerSocket.h>  
#include <transport/TBufferTransports.h>  
#include <concurrency/ThreadManager.h>  
#include <concurrency/PosixThreadFactory.h>  
#include <server/TThreadPoolServer.h>  
#include <server/TThreadedServer.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 boost::shared_ptr;  
  
class UserServiceHandler : virtual public UserServiceIf {  
 public:  
  UserServiceHandler() {  
    // Your initialization goes here  
  }  
  
  void add(const User& u) {  
    // Your implementation goes here  
    printf("uid=%s uname=%s usex=%d uage=%d\n", u.uid.c_str(), u.uname.c_str(), u.usex, u.uage);  
  }  
  
  void get(User& _return, const std::string& uid) {  
    // Your implementation goes here  
    _return.uid = "leo1";  
    _return.uname = "yueyue";  
    _return.usex = 1;  
    _return.uage = 3;  
    printf("uid=%s uname=%s usex=%d uage=%d\n", _return.uid.c_str(), _return.uname.c_str(), _return.usex, _return.uage);  
  }  
  
};  
  
int main(int argc, char **argv) {  
  shared_ptr<UserServiceHandler> handler(new UserServiceHandler());  
  shared_ptr<TProcessor> processor(new UserServiceProcessor(handler));  
  shared_ptr<TProtocolFactory> protocolFactory(new TCompactProtocolFactory());  
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());  
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));  
  
  shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(10);  
  shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());  
  threadManager->threadFactory(threadFactory);  
  threadManager->start();  
  printf("start user server...\n");  
  
  TThreadPoolServer server(processor, serverTransport, transportFactory, protocolFactory, threadManager);  
  server.serve();  
  return 0;  
}  

注意这段代码使用TCompactProtocol,需要#include <config.h> 
另外这个是Blocking的多线程服务器 

4.生成C++的client文件UserClient.cpp 

#include "UserService.h"  
#include <config.h>  
#include <transport/TSocket.h>  
#include <transport/TBufferTransports.h>  
#include <protocol/TCompactProtocol.h>  
  
using namespace apache::thrift;  
using namespace apache::thrift::protocol;  
using namespace apache::thrift::transport;  
  
using boost::shared_ptr;  
  
int main(int argc, char **argv) {  
        boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));  
        boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));  
        boost::shared_ptr<TProtocol> protocol(new TCompactProtocol(transport));  
  
        transport->open();  
  
        User u;  
        u.uid = "leo";  
        u.uname = "yueyue";  
        u.usex = 1;  
        u.uage = 3;  
  
        UserServiceClient client(protocol);  
        client.add(u);  
  
        User u1;  
        client.get(u1,"lll");  
  
        transport->close();  
        printf("uid=%s uname=%s usex=%d uage=%d\n", u1.uid.c_str(), u1.uname.c_str(), u1.usex, u1.uage);  
        return 0;  
}  

5.生成Makefile 

BOOST_DIR = /usr/local/include/boost/  
THRIFT_DIR = /usr/local/include/thrift  
LIB_DIR = /usr/local/lib  
GEN_SRC = ./gen-cpp/acsuser_types.cpp ./gen-cpp/acsuser_constants.cpp ./gen-cpp/UserService.cpp  
default: server client  
server: UserServer.cpp  
        g++ -g -o UserServer -I${THRIFT_DIR} -I${BOOST_DIR}  -I./gen-cpp -L${LIB_DIR} -lthrift UserServer.cpp ${GEN_SRC}  
client: UserClient.cpp  
        g++ -g -o UserClient -lm -pthread -lz -lrt -lssl -I${THRIFT_DIR} -I${BOOST_DIR}  -I./gen-cpp -L${LIB_DIR} -lthrift UserClient.cpp ${GEN_SRC}  
clean:  
        $(RM) -r UserServer UserClient  

6.启动c++ server 

./UserServer 

7.测试c++ client 

./UserClient  

8.写java client文件UserClient.java

import org.apache.thrift.TException;  
import org.apache.thrift.protocol.TCompactProtocol;  
import org.apache.thrift.protocol.TProtocol;  
import org.apache.thrift.transport.TFramedTransport;  
import org.apache.thrift.transport.TNonblockingSocket;  
import org.apache.thrift.transport.TSocket;  
import org.apache.thrift.transport.TTransport;  
import org.apache.thrift.transport.TTransportException;  
  
//import UserService.Client;  
  
public class UserClient {  
    private void start() {  
        try {  
            TTransport socket = new TSocket("localhost", 9090);  
            //TTransport transport = new TFramedTransport(socket);  
            TProtocol protocol = new TCompactProtocol(socket);  
  
            UserService.Client client = new UserService.Client(protocol);  
            socket.open();  
            System.out.println(client.get("lll"));  
  
            User u = new User();  
            u.uid="leojava";  
            u.uname="yueyue";  
            u.usex=true;  
            u.uage=3;  
            client.add(u);  
            socket.close();  
  
        } catch (TTransportException e) {  
            e.printStackTrace();  
        } catch (TException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public static void main(String[] args) {  
        UserClient c = new UserClient();  
        c.start();  
  
    }  
}  

编译和运行java client 

javac -classpath /usr/local/lib/libthrift-0.7.0.jar:/usr/local/lib/log4j-1.2.14.jar:/usr/local/lib/commons-logging-1.1.1.jar:/usr/local/lib/slf4j-api-1.5.8.jar UserClient.java ./gen-java/*.java  
java -classpath .:./gen-java:/usr/local/lib/libthrift-0.7.0.jar:/usr/local/lib/log4j-1.2.14.jar:/usr/local/lib/commons-logging-1.1.1.jar:/usr/local/lib/slf4j-api-1.5.8.jar:/usr/local/lib/slf4j-log4j12-1.5.8.jar UserClient 

9.写Python client文件PythonClient.py 

#!/usr/bin/env python  
import sys  
sys.path.append('./gen-py')  
from acsuser import UserService  
from acsuser.ttypes import *  
from thrift import Thrift  
from thrift.transport import TSocket  
from thrift.transport import TTransport  
from thrift.protocol import TCompactProtocol  
  
# Make socket  
transport = TSocket.TSocket('localhost', 9090)  
# Buffering is critical. Raw sockets are very slow  
transport = TTransport.TBufferedTransport(transport)  
# Wrap in a protocol  
protocol = TCompactProtocol.TCompactProtocol(transport)  
# Create a client to use the protocol encoder  
client = UserService.Client(protocol)  
# Connect!  
transport.open()  
# Call Server services    
u = client.get('lll')  
print 'uid=%s uname=%s usex=%d u.uage=%d' %(u.uid,u.uname,u.usex,u.uage)  
  
u1 = User()  
u1.uid='leo'  
u1.uname='yueyue'  
u1.usex=1  
u1.uage=3  
client.add(u1)  

执行python client代码 

chmod 777 PythonClient.py  
./PythonClient.py

抱歉!评论已关闭.