在Ubuntu上安装Thrift并调通一个例子
Thrift实际上是实现了C/S模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过thrift编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。它支持多种数据传输格式、数据传输方式和服务模型等,直接指定调用即可。
感谢好文:
所以我的也算个实际命令性贴子了。
0、准备篇
因为要用C++,所以必须装Boost。其它语言的依赖看官方Wiki。
下载Thrift:http://thrift.apache.org/download/ -> https://dist.apache.org/repos/dist/release/thrift/0.8.0/thrift-0.8.0.tar.gz
下载Boost:http://www.boost.org/ -> http://sourceforge.net/projects/boost/files/boost/1.51.0/boost_1_51_0.tar.gz/download
1、安装Boost
tar -xvzf boost_1_51_0.tar.gz
cd boost_1_51_0/
./bootstrap.sh
最终输出:Building Boost.Build engine with toolset gcc... tools/build/v2/engine/bin.linuxx86_64/b2 Detecting Python version... 2.6 Detecting Python root... /usr Unicode/ICU support for Boost.Regex?... not found. Generating Boost.Build configuration in project-config.jam... Bootstrapping is done. To build, run: ./b2 To adjust configuration, edit 'project-config.jam'. Further information: - Command line help: ./b2 --help - Getting started guide: http://www.boost.org/more/getting_started/unix-variants.html - Boost.Build documentation: http://www.boost.org/boost-build2/doc/html/index.html
./b2 install 搞完了报了一点小错,暂时没管,也证明没事。因为失败的占成功的比例太小了。
...failed updating 58 targets... ...skipped 12 targets...
Boost装到了/usr/local/include 和 /usr/local/lib里。因为这没加配置参数,这是默认结果。
2、安装Thrift
装Thrift之前的准备,依赖包提前装好:http://thrift.apache.org/docs/install/ubuntu/
因为我准备按官方Wiki上搞C++的Server,Python的Client。所以:
.
/configure
--with-cpp --with-boost=/usr/local
--with-python
--without-csharp --without-java --without-erlang --without-perl --without-php --without-php_extension --without-ruby --without-haskell --without-go
最终输出:
thrift 0.8.0 Building code generators ..... : Building C++ Library ......... : yes Building C (GLib) Library .... : no Building Java Library ........ : no Building C# Library .......... : no Building Python Library ...... : yes Building Ruby Library ........ : no Building Haskell Library ..... : no Building Perl Library ........ : no Building PHP Library ......... : no Building Erlang Library ...... : no Building Go Library .......... : no Building TZlibTransport ...... : yes Building TNonblockingServer .. : yes Using Python ................. : /usr/bin/python If something is missing that you think should be present, please skim the output of configure to find the missing component. Details are present in config.log.
make
sudo make install
3、试用例子
我用的是Thrift的官方例子:http://thrift.apache.org/
thrift --gen cpp UserProfile.thrift
thrift --gen py UserProfile.thrift
生成的文件在gen-cpp gen-py两个目录中。我用C++ Server端和Python的客户端。C++ Server相关:
UserStorage_server.skeleton.cpp注释掉或者去掉 using namespace ;(位置大概17行左右) 。这个是Server端的Main函数。Client的main函数文件要自己写。
C++编译选项:
编译服务端:g++ -g -I/usr/local/include/thrift/ -L/usr/local/lib -lthrift UserProfile_constants.cpp UserProfile_types.cpp UserStorage.cpp UserStorage_server.skeleton.cpp -o server -DHAVE_NETINET_IN_H
编译客户端:g++ -g -I/usr/local/include/thrift/ -L/usr/local/lib -lthrift -lm -pthread -lz -lrt -lssl UserProfile_constants.cpp UserProfile_types.cpp UserStorage.cpp client.cpp -o client -DHAVE_NETINET_IN_H
然后直接运行./server即顺。程序运行时加载共享库出现的错误时如下解决:
"error while loading shared libraries: xxxx: cannot open shared object file: No such file or directory"
解决步骤:
1、使用find命令查找缺失的xxxx共享库文件所在位置。参考:#find 目录 -name "xxxx*"
2、将找到的目录位置写入 /etc/ld.so.conf 配置文件,这个文件记录了编译时使用的动态链接库的路径。
3、然后使用ldconfig命令,使配置生效。
我的是在/usr/local/lib/里。
Python自己写的Client如下,运行即可:
import sys import pprint from urlparse import urlparse from thrift.transport import TTransport from thrift.transport import TSocket from thrift.transport import THttpClient from thrift.protocol import TBinaryProtocol import UserStorage from ttypes import * up = UserProfile(uid=1, name="Test User", blurb="Thrift is great") # Talk to a server via TCP sockets, using a binary protocol transport = TSocket.TSocket("localhost", 9090) transport.open() protocol = TBinaryProtocol.TBinaryProtocol(transport) # Use the service we already defined service = UserStorage.Client(protocol) service.store(up)
运行Python出错,主要是加环境变量和改代码,这个贴子讲的挺好。http://www.cnblogs.com/dkblog/archive/2011/09/09/2172136.html
我做了:
export PYTHONPATH=/usr/lib/python2.6/site-packages
4、Tutorial中的例子,另一个例子
cd {THRIFTHOME}/thrift-0.8.0/tutorial
thrift --gen cpp shared.thrift
thrift --gen cpp tutorial.thrift
搞完以后,gen-cpp中的Makefile要改一下:
BOOST_DIR = /usr/local/include/boost/ 后面加-DHAVE_NETINET_IN_H server: CppServer.cpp g++ -o CppServer -I${THRIFT_DIR} -I${BOOST_DIR} -I../gen-cpp -L${LIB_DIR} -lthrift CppServer.cpp ${GEN_SRC} -DHAVE_NETINET_IN_H client: CppClient.cpp g++ -o CppClient -I${THRIFT_DIR} -I${BOOST_DIR} -I../gen-cpp -L${LIB_DIR} -lthrift CppClient.cpp ${GEN_SRC} -DHAVE_NETINET_IN_H
Server和Client都起来就行。Client输出如下:
cpp$ ./CppClient ping() 1+1=2 InvalidOperation: Cannot divide by 0 15-10=5 Check log: 5
杂记:
Client直接向Server发消息,那怎么从Server端拿回Response呢?这个例子已经显示了。Thrift中如此定义这个函数的:
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
Client中这样就可以把Server的返回值拿回来了。
int32_t quotient = client.calculate(1, work);