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
//#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespace::apache::thrift;
usingnamespace::apache::thrift::protocol;
usingnamespace::apache::thrift::transport;
usingnamespace::apache::thrift::server;
usingnamespace::apache::thrift::concurrency;
usingboost::shared_ptr;
classUserServiceHandler :virtualpublicUserServiceIf {
public:
UserServiceHandler() {
// Your initialization goes here
}
voidadd(constUser& 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);
}
voidget(User& _return,conststd::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);
}
};
intmain(intargc,char**argv) {
shared_ptr handler(newUserServiceHandler());
shared_ptr processor(newUserServiceProcessor(handler));
shared_ptr protocolFactory(newTCompactProtocolFactory());
shared_ptr transportFactory(newTBufferedTransportFactory());
shared_ptr serverTransport(newTServerSocket(9090));
shared_ptr threadManager = ThreadManager::newSimpleThreadManager(10);
shared_ptr threadFactory = shared_ptr(newPosixThreadFactory());
threadManager->threadFactory(threadFactory);
threadManager->start();
printf("start user server...\n");
TThreadPoolServer server(processor, serverTransport, transportFactory, protocolFactory, threadManager);
server.serve();
return0;
}
#include "UserService.h"
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
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 handler(new UserServiceHandler());
shared_ptr processor(new UserServiceProcessor(handler));
shared_ptr protocolFactory(new TCompactProtocolFactory());
shared_ptr transportFactory(new TBufferedTransportFactory());
shared_ptr serverTransport(new TServerSocket(9090));
shared_ptr threadManager = ThreadManager::newSimpleThreadManager(10);
shared_ptr threadFactory = shared_ptr(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
另外这个是Blocking的多线程服务器
4.生成C++的client文件UserClient.cpp
C++代码
#include "UserService.h"
#include
#include
#include
#include
usingnamespaceapache::thrift;
usingnamespaceapache::thrift::protocol;
usingnamespaceapache::thrift::transport;
usingboost::shared_ptr;
intmain(intargc,char**argv) {
boost::shared_ptr socket(newTSocket("localhost", 9090));
boost::shared_ptr transport(newTBufferedTransport(socket));
boost::shared_ptr protocol(newTCompactProtocol(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);
return0;
}
#include "UserService.h"
#include
#include
#include
#include
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 socket(new TSocket("localhost", 9090));
boost::shared_ptr transport(new TBufferedTransport(socket));
boost::shared_ptr 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代码
importorg.apache.thrift.TException;
importorg.apache.thrift.protocol.TCompactProtocol;
importorg.apache.thrift.protocol.TProtocol;
importorg.apache.thrift.transport.TFramedTransport;
importorg.apache.thrift.transport.TNonblockingSocket;
importorg.apache.thrift.transport.TSocket;
importorg.apache.thrift.transport.TTransport;
importorg.apache.thrift.transport.TTransportException;
//import UserService.Client;
publicclassUserClient {
privatevoidstart() {
try{
TTransport socket =newTSocket("localhost",9090);
//TTransport transport = new TFramedTransport(socket);
TProtocol protocol =newTCompactProtocol(socket);
UserService.Client client =newUserService.Client(protocol);
socket.open();
System.out.println(client.get("lll"));
User u =newUser();
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();
}
}
publicstaticvoidmain(String[] args) {
UserClient c =newUserClient();
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
importsys
sys.path.append('./gen-py')
fromacsuserimportUserService
fromacsuser.ttypesimport*
fromthriftimportThrift
fromthrift.transportimportTSocket
fromthrift.transportimportTTransport
fromthrift.protocolimportTCompactProtocol
# 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代码
chmod777PythonClient.py
./PythonClient.py