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


    转自:http://blog.csdn.net/andy_yf/article/details/7487384

    thrift做为跨语言调用的方案有高效,支持语言较多,成熟等优点;代码侵入较强是其弱点。 
    下面记录以C++做服务器,C++,javapython做客户端的示例,这个和本人现在工作环境吻合,使用多线程长连接的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++服务端代码

    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
    ", 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
    ", _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...
    ");    
    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
    ", 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  
  • 相关阅读:
    IISManager 的启动
    基于hadoop集群的hive 安装(mysql,derby)
    Struts中央控制器
    在Spring中配置Hibernate事务
    java 实现多线程下载
    hello,博客园
    easyui datagrid中添加右键菜单事件
    C#项目打包
    easyui datagrid中单击添加菜单事件
    SQL多条件查询拼接in中条件方法
  • 原文地址:https://www.cnblogs.com/lpxblog/p/5384891.html
Copyright © 2020-2023  润新知