Apache Thrift 配置和使用指南
2017-03-16 12:00
946 查看
Thrift 安装
Mac 下 Thrift 安装
快速安装
使用 Mac 的包管理器 Homebrew。首先安装 Homebrew:ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"[/code]
使用 Homebrew 安装 thrift:brew install thrift
如需手动安装特定版本,请参考以下若干小节。手动安装
首先编译安装 Thrift 的依赖 Boost 和 libevent,然后编译安装 Thrift。安装 Boost
在 boost.org 下载 boost 库,解压进入文件夹,并通过以下命令编译:./bootstrap.sh sudo ./b2 threading=multi address-model=64 variant=release stage install
Boost 库是对 C++ 标准库提供扩展的一些 C++ 程序库的总称。安装 libevent
在 libevent.org 下载 libevent, 解压并通过如下命令编译安装:./configure --prefix=/usr/local make sudo make install
libevent 是用 C 语言编写的、轻量级开源高性能网络库,基于事件驱动且支持跨平台。安装 Apache Thrift
下载最新版本的 Apache Thrift,解压并通过如下命令编译安装:./configure --prefix=/usr/local/ \ --with-boost=/usr/local \ --with-libevent=/usr/local \ --without-ruby ## 不需要的语言可以通过 --without-[language] 去掉
运行时可能会报错:Bison version 2.5 or higher must be installed on the system!。参考 How to install bison on mac OSX 解决:brew install bison brew link bison --forcebrew link bison是在系统路径下添加 bison 的 symlinks。在装完 thrift 之后记得:brew unlink bisonUbuntu 下 Thrift 配置
参考链接
[1] Debian/Ubuntu install
[2] Building from source
[3] Apache Thrift Tutorial安装依赖
执行命令:sudo apt-get install automake bison flex g++ git libboost1.55-all-dev libevent-dev libssl-dev libtool make pkg-config安装 Thrift
在 Thrift 官网 下载最新的打包文件,解压后进入文件夹,输入如下命令编译安装:./configure && make && sudo make installThrift C++ 实例
本节中我们实现一个简单的加减乘除计算器 C/S 实例。基本过程
编写接口描述文件 calculator.thrift,定义数据类型和服务接口
编译 calculator.thrift 生成 gen-cpp 源代码文件夹
编写 server 代码,引用 gen-cpp 与 thrift 库目录编译
编写 client 代码,引用 gen-cpp 与 thrift 库目录编译
运行 ./server
运行 ./clientThrift 脚本
假设服务端(Server)为客户端(Client)提供简单的数学运算功能,编写 calculator.thrift 脚本文件如下:namespace cpp MathServer service MathService{ i32 add (1:i32 a, 2:i32 b), i32 sub (1:i32 a, 2:i32 b), i32 mul (1:i32 a, 2:i32 b), i32 div (1:i32 a, 2:i32 b), i32 mod (1:i32 a, 2:i32 b) }
编译 Thrift 脚本的基本命令格式为:thrift --gen <language> <Thrift filename>
如果在一个 .thrift 文件里包含了其他的 .thrift 文件,需要递归编译,执行:thrift --gen -r <language> <Thrift filename>
本例中,我们执行如下命令编译:thrift --gen cpp calculator.thrift
在当前目录下会生成一个 gen-cpp 文件夹。文件夹里包含 MathService.h/cpp, calculator_constants.h/cpp, calculator_types.h/cpp 和 MathService_server.skeleton.cpp 7 个文件。前 6 个文件用于接口定义,需要同时被 Client 和 Server 代码引用(调用或实现),而 MathService_server.skeleton.cpp 则提供了 Server 端代码的一个基本框架。Server 程序
新建 calculator 文件夹,把 gen-cpp 复制进去,并将 gen-cpp 里的 MathService_server.skeleton.cpp 重命名为 server.cpp,移动到 server 文件夹。实现 server.cpp 后的完整代码如下:// This autogenerated skeleton file illustrates how to build a server. // You should copy it to another filename to avoid overwriting it. #include "gen-cpp/MathService.h" #include <iostream> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/server/TSimpleServer.h> #include <thrift/transport/TServerSocket.h> #include <thrift/transport/TBufferTransports.h> using namespace ::apache::thrift; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; using namespace ::apache::thrift::server; using boost::shared_ptr; using namespace ::MathServer; class MathServiceHandler : virtual public MathServiceIf { public: MathServiceHandler() { // Your initialization goes here } int32_t add(const int32_t a, const int32_t b) { return a + b; } int32_t sub(const int32_t a, const int32_t b) { return a - b; } int32_t mul(const int32_t a, const int32_t b) { return a * b; } int32_t div(const int32_t a, const int32_t b) { return a / b; } int32_t mod(const int32_t a, const int32_t b) { return a % b; } }; int main(int argc, char** argv) { int port = 9090; shared_ptr<MathServiceHandler> handler(new MathServiceHandler()); shared_ptr<TProcessor> processor(new MathServiceProcessor(handler)); shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); std::cout << "Start server..." << std::endl; server.serve(); return 0; }Client 程序
在 calculator 文件夹里新建 client.cpp 文件,代码如下:#include <iostream> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/transport/TSocket.h> #include <thrift/transport/TTransportUtils.h> #include "gen-cpp/MathService.h" using namespace std; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using boost::shared_ptr; using namespace ::MathServer; int main(int argc, char** argv) { int port = 9090; boost::shared_ptr<TTransport> socket(new TSocket("localhost", port)); boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); MathServiceClient client(protocol); try { transport->open(); cout << "1 + 1 = " << client.add(1, 1) << endl; cout << "1 * 2 = " << client.mul(1, 2) << endl; cout << "8 / 2 = " << client.div(8, 2) << endl; transport->close(); } catch (TException& tx) { cout << "ERROR: " << tx.what() << endl; } }编译
用 g++ 编译,先针对各个 .cpp 文件生成 .o 目标,然后链接 thrift 库,生成可执行文件 client 和 server。由于 thrift 里用到 c++11 里的 bind 方法,需要指定-std=c++11。假设 thrift 库安装在 /usr/local/lib 里,thrift 的头文件在 /usr/local/include/thrift 中,则完整的编译命令如下:# build object files g++ -I/usr/local/include -std=c++11 -c -o \ gen-cpp/calculator_constants.o gen-cpp/calculator_constants.cpp g++ -I/usr/local/include -std=c++11 -c -o \ gen-cpp/calculator_types.o gen-cpp/calculator_types.cpp g++ -I/usr/local/include -std=c++11 -c -o \ gen-cpp/MathService.o gen-cpp/MathService.cpp # build server.o g++ -I/usr/local/include -std=c++11 -c -o \ server.o server.cpp # build client.o g++ -I/usr/local/include -std=c++11 -c -o \ client.o client.cpp # build target files: client, server g++ -L/usr/local/lib -lthrift -o server server.o \ gen-cpp/calculator_constants.o gen-cpp/calculator_types.o \ gen-cpp/MathService.o g++ -L/usr/local/lib -lthrift -o client client.o \ gen-cpp/calculator_constants.o gen-cpp/calculator_types.o \ gen-cpp/MathService.o # clear *.o rm ./*.o gen-cpp/*.o
可以直接执行以上命令,也可以将以上命令写进一个 build.sh 文件里,然后执行:sh ./build.sh
生成完 client 和 server 后,分别在两个终端执行./server和./client,可以分别看到Start server...和1 + 1 = 2 ...。
综上。Thrift 脚本语法
Thrift 用于跨语言的 RPC 通信,因此其接口定义文件*.thrift中包含的数据结构与函数定义必须对于不同语言都适用。官网的 Thrift Wiki Tutorial 基本包含了所有的 Thrift 语法,无须赘述,这里只是把它复制过来:# # Thrift Tutorial # Mark Slee (mcslee@facebook.com) # # This file aims to teach you how to use Thrift, in a .thrift file. Neato. The # first thing to notice is that .thrift files support standard shell comments. # This lets you make your thrift file executable and include your Thrift build # step on the top line. And you can place comments like this anywhere you like. # # Before running this file, you will need to have installed the thrift compiler # into /usr/local/bin. /** * The first thing to know about are types. The available types in Thrift are: * * bool Boolean, one byte * byte Signed byte * i16 Signed 16-bit integer * i32 Signed 32-bit integer * i64 Signed 64-bit integer * double 64-bit floating point value * string String * map<t1,t2> Map from one type to another * list<t1> Ordered list of one type * set<t1> Set of unique elements of one type * * Did you also notice that Thrift supports C style comments? */ // Just in case you were wondering... yes. We support simple C comments too. /** * Thrift files can reference other Thrift files to include common struct * and service definitions. These are found using the current path, or by * searching relative to any paths specified with the -I compiler flag. * * Included objects are accessed using the name of the .thrift file as a * prefix. i.e. shared.SharedObject */ include "shared.thrift" /** * Thrift files can namespace, package, or prefix their output in various * target languages. */ namespace cpp tutorial namespace java tutorial php_namespace tutorial namespace perl tutorial namespace smalltalk.category Thrift.Tutorial /** * Thrift lets you do typedefs to get pretty names for your types. Standard * C style here. */ typedef i32 MyInteger /** * Thrift also lets you define constants for use across languages. Complex * types and structs are specified using JSON notation. */ const i32 INT32CONSTANT = 9853 const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} /** * You can define enums, which are just 32 bit integers. Values are optional * and start at 1 if not supplied, C style again. * ^ ThriftIDL page says "If no constant value is supplied, * the value is either 0 for the first element, or one greater than the * preceding value for any subsequent element" so I'm guessing that's a bug. * PS: http://enel.ucalgary.ca/People/Norman/enel315_winter1997/enum_types/ states that if values are not supplied, they start at 0 and not 1. */ enum Operation { ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4 } /** * Structs are the basic complex data structures. They are comprised of fields * which each have an integer identifier, a type, a symbolic name, and an * optional default value. * * Fields can be declared "optional", which ensures they will not be included * in the serialized output if they aren't set. Note that this requires some * manual management in some languages. */ struct Work { 1: i32 num1 = 0, 2: i32 num2, 3: Operation op, 4: optional string comment, } /** * Structs can also be exceptions, if they are nasty. */ exception InvalidOperation { 1: i32 what, 2: string why } /** * Ahh, now onto the cool part, defining a service. Services just need a name * and can optionally inherit from another service using the extends keyword. */ service Calculator extends shared.SharedService { /** * A method definition looks like C code. It has a return type, arguments, * and optionally a list of exceptions that it may throw. Note that argument * lists and exception lists are specified using the exact same syntax as * field lists in struct or exception definitions. NOTE: Overloading of * methods is not supported; each method requires a unique name. */ void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), /** * This method has an oneway modifier. That means the client only makes * a request and does not listen for any response at all. Oneway methods * must be void. * * The server may execute async invocations of the same client in parallel/ * out of order. */ oneway void zip(), } /** * It's possible to declare more than one service per Thrift file. */ service CalculatorExtreme extends shared.SharedService { void pingExtreme(), } /** * That just about covers the basics. Take a look in the test/ folder for more * detailed examples. After you run this file, your generated code shows up * in folders with names gen-<language>. The generated code isn't too scary * to look at. It even has pretty indentation. */参考链接
[1] Apache Thrift OS X Setup
[2] mac os x10.10 安装thrift
[3] Thrift C++ Tutorial
相关文章推荐
- Softice使用指南---配置Softice
- (转)软件配置管理与SourceSafe使用指南(上)
- 在 Windows 上使用 Apache 2 配置 Subversion 服务器
- (转)Apache 中 KeepAlive 配置的合理使用
- Quartz.net官方开发指南 第十课: 配置、资源使用以及SchedulerFactory
- Win32平台下Apache+ssl配置指南
- Quartz.net官方开发指南 第十课: 配置、资源使用以及SchedulerFactory
- Quartz.net官方开发指南 第十课: 配置、资源使用以及SchedulerFactory
- pgpool-II使用指南-安装与配置(簡體)
- 在apache配置文件中使用IfDefine以及IfModule指令来快速更改配置
- 配置简单的subversion认证(使用apache2.0.59模块部分认证) windows xp
- 软件配置管理与SourceSafe使用指南(mi6236)
- CVS安装配置与使用指南
- Apache2.2.4+PHP5.2.0+Tomcat5.0配置指南!
- (转)软件配置管理与SourceSafe使用指南(下)
- (转)软件配置管理与SourceSafe使用指南(中)
- Apache 中 KeepAlive 配置的合理使用
- 使用apache common configuration读取配置文件或修改配置文件
- JDK/Resin/Tomcat/Apache配置指南
- Windows下配置SVN 1.4.5 + APACHE 2.2.6使用域认证