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

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

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

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

1.定义idl文件acsuser.thrift 

  1. struct User{    
  2.  1: string uid,    
  3.  2: string uname,    
  4.  3: bool usex,    
  5.  4: i16 uage,    
  6. }    
  7. service UserService{    
  8.  void add(1: User u),    
  9.  User get(1: string uid),    
  10. }    

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

  1. thrift -r --gen cpp acsuser.thrift     
  2. thrift -r --gen java acsuser.thrift     
  3. thrift -r --gen py acsuser.thrift    

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

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

修改UserServer.cpp 

  1. #include "UserService.h"    
  2. #include <config.h>    
  3. //#include <protocol/TBinaryProtocol.h>    
  4. #include <protocol/TCompactProtocol.h>    
  5. #include <server/TSimpleServer.h>    
  6. #include <transport/TServerSocket.h>    
  7. #include <transport/TBufferTransports.h>    
  8. #include <concurrency/ThreadManager.h>    
  9. #include <concurrency/PosixThreadFactory.h>    
  10. #include <server/TThreadPoolServer.h>    
  11. #include <server/TThreadedServer.h>    
  12.     
  13. using namespace ::apache::thrift;    
  14. using namespace ::apache::thrift::protocol;    
  15. using namespace ::apache::thrift::transport;    
  16. using namespace ::apache::thrift::server;    
  17. using namespace ::apache::thrift::concurrency;    
  18.     
  19. using boost::shared_ptr;    
  20.     
  21. class UserServiceHandler : virtual public UserServiceIf {    
  22.  public:    
  23.   UserServiceHandler() {    
  24.     // Your initialization goes here    
  25.   }    
  26.     
  27.   void add(const User& u) {    
  28.     // Your implementation goes here    
  29.     printf("uid=%s uname=%s usex=%d uage=%d\n", u.uid.c_str(), u.uname.c_str(), u.usex, u.uage);    
  30.   }    
  31.     
  32.   void get(User& _return, const std::string& uid) {    
  33.     // Your implementation goes here    
  34.     _return.uid = "leo1";    
  35.     _return.uname = "yueyue";    
  36.     _return.usex = 1;    
  37.     _return.uage = 3;    
  38.     printf("uid=%s uname=%s usex=%d uage=%d\n", _return.uid.c_str(), _return.uname.c_str(), _return.usex, _return.uage);    
  39.   }    
  40.     
  41. };    
  42.     
  43. int main(int argc, char **argv) {    
  44.   shared_ptr<UserServiceHandler> handler(new UserServiceHandler());    
  45.   shared_ptr<TProcessor> processor(new UserServiceProcessor(handler));    
  46.   shared_ptr<TProtocolFactory> protocolFactory(new TCompactProtocolFactory());    
  47.   shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());    
  48.   shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));    
  49.     
  50.   shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(10);    
  51.   shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());    
  52.   threadManager->threadFactory(threadFactory);    
  53.   threadManager->start();    
  54.   printf("start user server...\n");    
  55.     
  56.   TThreadPoolServer server(processor, serverTransport, transportFactory, protocolFactory, threadManager);    
  57.   server.serve();    
  58.   return 0;    
  59. }    

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

4.生成C++的client文件UserClient.cpp 
  1. #include "UserService.h"    
  2. #include <config.h>    
  3. #include <transport/TSocket.h>    
  4. #include <transport/TBufferTransports.h>    
  5. #include <protocol/TCompactProtocol.h>    
  6.     
  7. using namespace apache::thrift;    
  8. using namespace apache::thrift::protocol;    
  9. using namespace apache::thrift::transport;    
  10.     
  11. using boost::shared_ptr;    
  12.     
  13. int main(int argc, char **argv) {    
  14.         boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));    
  15.         boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));    
  16.         boost::shared_ptr<TProtocol> protocol(new TCompactProtocol(transport));    
  17.     
  18.         transport->open();    
  19.     
  20.         User u;    
  21.         u.uid = "leo";    
  22.         u.uname = "yueyue";    
  23.         u.usex = 1;    
  24.         u.uage = 3;    
  25.     
  26.         UserServiceClient client(protocol);    
  27.         client.add(u);    
  28.     
  29.         User u1;    
  30.         client.get(u1,"lll");    
  31.     
  32.         transport->close();    
  33.         printf("uid=%s uname=%s usex=%d uage=%d\n", u1.uid.c_str(), u1.uname.c_str(), u1.usex, u1.uage);    
  34.         return 0;    
  35. }    
5.生成Makefile 
  1. BOOST_DIR = /usr/local/include/boost/    
  2. THRIFT_DIR = /usr/local/include/thrift    
  3. LIB_DIR = /usr/local/lib    
  4. GEN_SRC = ./gen-cpp/acsuser_types.cpp ./gen-cpp/acsuser_constants.cpp ./gen-cpp/UserService.cpp    
  5. default: server client    
  6. server: UserServer.cpp    
  7.         g++ -g -o UserServer -I${THRIFT_DIR} -I${BOOST_DIR}  -I./gen-cpp -L${LIB_DIR} -lthrift UserServer.cpp ${GEN_SRC}    
  8. client: UserClient.cpp    
  9.         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}    
  10. clean:    
  11.         $(RM) -r UserServer UserClient    

6.启动c++ server 
  1. ./UserServer   

7.测试c++ client 
  1. ./UserClient    

8.写java client文件UserClient.java
  1. import org.apache.thrift.TException;    
  2. import org.apache.thrift.protocol.TCompactProtocol;    
  3. import org.apache.thrift.protocol.TProtocol;    
  4. import org.apache.thrift.transport.TFramedTransport;    
  5. import org.apache.thrift.transport.TNonblockingSocket;    
  6. import org.apache.thrift.transport.TSocket;    
  7. import org.apache.thrift.transport.TTransport;    
  8. import org.apache.thrift.transport.TTransportException;    
  9.     
  10. //import UserService.Client;    
  11.     
  12. public class UserClient {    
  13.     private void start() {    
  14.         try {    
  15.             TTransport socket = new TSocket("localhost", 9090);    
  16.             //TTransport transport = new TFramedTransport(socket);    
  17.             TProtocol protocol = new TCompactProtocol(socket);    
  18.     
  19.             UserService.Client client = new UserService.Client(protocol);    
  20.             socket.open();    
  21.             System.out.println(client.get("lll"));    
  22.     
  23.             User u = new User();    
  24.             u.uid="leojava";    
  25.             u.uname="yueyue";    
  26.             u.usex=true;    
  27.             u.uage=3;    
  28.             client.add(u);    
  29.             socket.close();    
  30.     
  31.         } catch (TTransportException e) {    
  32.             e.printStackTrace();    
  33.         } catch (TException e) {    
  34.             e.printStackTrace();    
  35.         }    
  36.     }    
  37.     
  38.     public static void main(String[] args) {    
  39.         UserClient c = new UserClient();    
  40.         c.start();    
  41.     
  42.     }    
  43. }    

编译和运行java client 
  1. 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    
  2. 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 
  1. #!/usr/bin/env python    
  2. import sys    
  3. sys.path.append('./gen-py')    
  4. from acsuser import UserService    
  5. from acsuser.ttypes import *    
  6. from thrift import Thrift    
  7. from thrift.transport import TSocket    
  8. from thrift.transport import TTransport    
  9. from thrift.protocol import TCompactProtocol    
  10.     
  11. # Make socket    
  12. transport = TSocket.TSocket('localhost', 9090)    
  13. # Buffering is critical. Raw sockets are very slow    
  14. transport = TTransport.TBufferedTransport(transport)    
  15. # Wrap in a protocol    
  16. protocol = TCompactProtocol.TCompactProtocol(transport)    
  17. # Create a client to use the protocol encoder    
  18. client = UserService.Client(protocol)    
  19. # Connect!    
  20. transport.open()    
  21. # Call Server services      
  22. u = client.get('lll')    
  23. print 'uid=%s uname=%s usex=%d u.uage=%d' %(u.uid,u.uname,u.usex,u.uage)    
  24.     
  25. u1 = User()    
  26. u1.uid='leo'    
  27. u1.uname='yueyue'    
  28. u1.usex=1    
  29. u1.uage=3    
  30. client.add(u1)    

执行python client代码 
  1. chmod 777 PythonClient.py    
  2. ./PythonClient.py 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值