linux上安装thrift见
http://jinghong.iteye.com/blog/1102535
thrift做为跨语言调用的方案有高效,支持语言较多,成熟等优点;代码侵入较强是其弱点。
下面记录以C++做服务器,C++,java和python做客户端的示例,这个和本人现在工作环境吻合,使用多线程长连接的socket来建立高效分布式系统的跨语言调用平台。
遗憾的是目前版本(0.7.0)的C语言还不支持Compact协议,导致在现在的环境中nginx c module调用thrift要使用binary协议。thrift开发团队似乎对C语言不太感冒。
1.定义idl文件acsuser.thrift
Idl代码
- 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),
- }
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代码框架
Shell代码
- thrift -r --gen cpp acsuser.thrift
- thrift -r --gen java acsuser.thrift
- thrift -r --gen py acsuser.thrift
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++服务端代码
Shell代码
- cp gen-cpp/UserService_server.skeleton.cpp UserServer.cpp
cp gen-cpp/UserService_server.skeleton.cpp UserServer.cpp
修改UserServer.cpp
C++代码
- #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;
- }
#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
C++代码
- #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;
- }
#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
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
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
Shell代码
- ./UserServer
./UserServer
7.测试c++ client
Shell代码
- ./UserClient
./UserClient
8.写java client文件UserClient.java
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();
- }
- }
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
Shell代码
- 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
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
Python代码
- #!/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)
#!/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代码
Shell代码
- chmod 777 PythonClient.py
- ./PythonClient.py
时间: 2024-10-28 22:35:38