Apache Thrift的简单使用
Apache Thrift的简单使用
----------------------
1. 简介
Thrift是Facebook的一个开源项目,主要是一个跨语言的服务开发框架。它有一个代码生成器来对它所定义的IDL定义文件自己主动生成服务代码框架。用户仅仅要在其之前进行二次开发即可,对于底层的RPC通讯等都是透明的。眼下它支持的语言有C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml.
2. 下载与安装
能够在http://incubator.apache.org/thrift/download/去下载它的最新版本号,眼下最新版本号是0.5.0。另外你也能够check出它的svn,方法例如以下:
svn co http://svn.apache.org/repos/asf/thrift/trunk thrift
cd thrift
在它的jira中看到,它的0.6版本号也非常快就会出来了。
我的本本是debian 6.0,假设用ubuntu的兄弟安装方法也是一样的
tar -zxvf thrift-0.5.0.tar.gz
cd thrift-0.5.0
./configure
make
sudo make install
这时thrift的代码生成器和一些库文件就生成好了。
你能够用例如以下命令看一下thrift的版本号信息
thrift -version
3. 一个简单的样例
在thrift源码文件夹有一个叫tutorial的文件夹,进行当中后执行thrift命令生成对应的服务代码:
$ thrift -r --gen cpp tutorial.thrift // -r对当中include的文件也生成服务代码 -gen是生成服务代码的语言
执行完之后会在当前文件夹看到一个gen-cpp文件夹,当中就是thrfit命令生成的代码
这时你cd到tutorial/cpp文件夹,执行make,生成对应的CppServer与CppClient程式。
这时你能够用./CppServer执行服务端,让其监听一个特定的port
这时你能够用./CppClient执行client程式,让其去连接服务端,调用其所相应的服务。默认调用后会输出例如以下信息:
lemo@debian:~/Workspace/Facebook/Thrift/thrift-0.5.0/tutorial/cpp$ ./CppServer
Starting the server...
ping()
add(1,1)
calculate(1,{4,1,0})
calculate(1,{2,15,10})
getStruct(1)
假设你的终端中也出现了如上的信息,恭喜你,执行成功了。假设在执行CppServer的时候找不到动态库,看看你是不是执行了make install,假设执行了,再执行一下sudo ldconfig试试。再用ldd CppServer看一下它有没有找到对应的动态库了。
4. 样例分析
4.1 Thrift IDL的分析
这边有两个IDL文件,内容例如以下:
shared.thrift
---------------
**
* This Thrift file can be included by other Thrift files that want to share
* these definitions.
*/
namespace cpp shared
namespace java shared
namespace perl shared
// 这里定义了一个结构体,未定义方法,相应于生成的代码在gen-cpp中的shared_types.h中,当中有一个class叫SharedStruct,
// 有没有看到当中有两个方法叫read和write,这就是用来对其进行序列化与把序列化的方法.
// 对了,当中的i32是Thrift IDL中定义的变量类型,相应于c++语言中的int32_t
struct SharedStruct {
1: i32 key
2: string value
}
// 这里定义的一个服务,它语义上相似于面向对象中的定义一个接口,thrift的编译器会对其产生一套实现其接口的client与服务端方法
// 服务的一般定义格式例如以下
// service <name>
// <returntype> <name>(<arguments>)
// [ throws (<exceptions>)]
// ...
// }
service SharedService {
SharedStruct getStruct(1: i32 key)
}
tutorial.thrift
----------------
/**
* 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
*/
// 这个IDL包括了还有一个IDL,也就是说还有一个IDL中的对象与服务对其时可见的
include "shared.thrift"
/**
* Thrift files can namespace, package, or prefix their output in various
* target languages.
*/
// 这里定义了一些语言的namespace空间
namespace cpp tutorial
namespace java tutorial
namespace php tutorial
namespace perl 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.
*/
// 定义枚举类型
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, //这里的optional字段类型表示假设这个字段的值没有被赋值,它就不会被序列化输出
}
/**
* 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.
*/
// 这里是定义服务,它继承了shared的服务
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.
*/
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 a oneway modifier. That means the client only makes
* a request and does not listen for any response at all. Oneway methods
* must be void.
*/
oneway void zip()
}
4.2 服务端与client代码的分析
4.2.1 c++服务端
在tutorial/cpp文件夹中的CppServer.cpp是它的服务代码,主要分成两部分,
一部分是main方法用于做一些初始化与服务的启动,第二部分对于IDL中定义的接口的实现
int main(int argc, char **argv) {
// 定义了RPC的协议工厂,这里使用了二进制协议,你不能够使用别的协议,如JSON,Compact等
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
// 这里生成用户实现的CalculatorHandler服务,再把其帮定到一个Processor上去,它主要用于处理协议的输入与输出流
shared_ptr<CalculatorHandler> handler(new CalculatorHandler());
shared_ptr<TProcessor> processor(new CalculatorProcessor(handler));
// 生成一个传输通道,这里使用了Socket方式
shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));
// 生成一个传输工厂,主要用于把上面的transport转换成一个新的应用层传输通道
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
// 生成一个简单的服务端,这是一个单线程的服务端
TSimpleServer server(processor,
serverTransport,
transportFactory,
protocolFactory);
// 你也能够生成一个多线程的服务端,就是对其添�线程池。但它如今还不支持进程池,但可能会在0.7版本号中进行支持。
/**
* Or you could do one of these
shared_ptr<ThreadManager> threadManager =
ThreadManager::newSimpleThreadManager(workerCount);
shared_ptr<PosixThreadFactory> threadFactory =
shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
threadManager->threadFactory(threadFactory);
threadManager->start();
TThreadPoolServer server(processor,
serverTransport,
transportFactory,
protocolFactory,
threadManager);
TThreadedServer server(processor,
serverTransport,
transportFactory,
protocolFactory);
*/
printf("Starting the server.../n");
server.serve(); // 启动服务
printf("done./n");
return 0;
}
还有一部分例如以下:
// 这一部分主要是实现接口类,用于提供给对应的服务使用。
class CalculatorHandler : public CalculatorIf {
public:
CalculatorHandler() {}
void ping() {
printf("ping()/n");
}
int32_t add(const int32_t n1, const int32_t n2) {
...
}
int32_t calculate(const int32_t logid, const Work &work) {
...
}
void getStruct(SharedStruct &ret, const int32_t logid) {
...
}
void zip() {
printf("zip()/n");
}
protected:
map<int32_t, SharedStruct> log;
};
4.2.2 c++client
int main(int argc, char** argv) {
// 生成一个Socket连接到服务端
shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
// 对Socket通道添�缓冲功能
shared_ptr<TTransport> transport(new TBufferedTransport(socket));
// 生成对应的二进制协议,这个要和服务端一致,不然会出现协议版本号不正确的错误
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
// 生成client的服务对象
CalculatorClient client(protocol);
try {
transport->open(); // 加开服务
// 调用事先定义好的服务接口
client.ping();
printf("ping()/n");
int32_t sum = client.add(1,1);
printf("1+1=%d/n", sum);
Work work;
work.op = Operation::DIVIDE;
work.num1 = 1;
work.num2 = 0;
try {
int32_t quotient = client.calculate(1, work);
printf("Whoa? We can divide by zero!/n");
} catch (InvalidOperation &io) {
printf("InvalidOperation: %s/n", io.why.c_str());
}
work.op = Operation::SUBTRACT;
work.num1 = 15;
work.num2 = 10;
int32_t diff = client.calculate(1, work);
printf("15-10=%d/n", diff);
// Note that C++ uses return by reference for complex types to avoid
// costly copy construction
SharedStruct ss;
client.getStruct(ss, 1);
printf("Check log: %s/n", ss.value.c_str());
// 关闭服务
transport->close();
} catch (TException &tx) {
printf("ERROR: %s/n", tx.what());
}
}
4.2.3 其他代码的实现
在tutorial文件夹中有其他代码的样例,如erl,java,python,perl,ruby等。
5 參考
1. http://incubator.apache.org/thrift/
2. http://incubator.apache.org/thrift/static/thrift-20070401.pdf
Apache Thrift的简单使用的更多相关文章
- Apache Thrift的简单介绍
1.什么是Thrift thrift是一种可伸缩的跨语言服务的发展软件框架.它结合了功能强大的软件堆栈的代码生成引擎,以建设服务.不同开发语言开发的服务可以通过该框架实现通信. thrift是face ...
- Apache thrift RPC 双向通信
在上一篇介绍Apache thrift 安装和使用,写了一个简单的demo,讲解thrift服务的发布和客户端调用,但只是单向的客户端发送消息,服务端接收消息.而客户端却得不到服务器的响应. 在不涉及 ...
- Apache Thrift 跨语言服务开发框架
Apache Thrift 是一种支持多种编程语言的远程服务调用框架,由 Facebook 于 2007 年开发,并于 2008 年进入 Apache 开源项目管理.Apache Thrift 通过 ...
- Apache Thrift 服务开发框架学习记录
Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架. 前言: 目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Servic ...
- Apache Thrift - 可伸缩的跨语言服务开发框架
To put it simply, Apache Thrift is a binary communication protocol 原文地址:http://www.ibm.com/developer ...
- Apache Thrift学习之二(基础及原理)
Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架.本文将从 Java 开发人员角度详细介绍 Apache Thrift 的架构.开发和部署,并且 ...
- Apache Thrift学习之一(入门及Java实例演示)
目录: 概述 下载配置 基本概念 数据类型 服务端编码基本步骤 客户端编码基本步骤 数据传输协议 实例演示(java) thrift生成代码 实现接口Iface TSimpleServer服务模型 T ...
- Apache Thrift入门(安装、测试与java程序编写)
安装Apache Thrift ubuntu linux运行: #!/bin/bash #下载 wget http://mirrors.cnnic.cn/apache/thrift/0.9.1/thr ...
- 【Java】分布式RPC通信框架Apache Thrift 使用总结
简介 Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于th ...
随机推荐
- 安装好maven后,在cmd中运行mvn报一下的错误
当然报错,你这个路径下并没有pom.xml文件.你可以运行这个命令: mvn -version.
- python list comprehension twos for loop 嵌套for循环
list comprehension 后面可以有多个for loops,每个for后面可以有if [(x, y, x * y)for x in(0,1,2,3)for y in(0,1,2,3)if ...
- jQuery入门学习贴
先引一下阮一峰大牛翻译的书<软件随想录>中的一句话: “ joel认为,软件开发,最缺的是天才.而我认为,最缺的是全才.什么“全”:全面.全局.全心全意.全力以赴. ” 最近再学习jQue ...
- 51cto培训课程
课程: 云计算: OpenStack | 虚拟化 | 云平台 | Office 365 | 云服务 | Docker | 其他 大数据: Spark | Hadoop | Storm | Hive | ...
- android 获取本机号码需要root吗?
首先要明白,有的手机是获取不到自身的手机号的, 查了些资料,有以下两种方式可以获取到: 1. 通过对方给你发短信,打电话获取本机号码: 2. 还有一个就是通过APN来查询,但是这 ...
- 关于String.concat()方法和StringBuffer.append()方法的学习:方法是如何追加字符到源字符串的
问题分析: 首先,看看两段代码的运行结果,两段代码分别是: 第一段代码,关于String.concat()方法的测试: public static void main(String[] args) { ...
- Android apk逆向实战
简介 逆向Android apk其实是一个分析Android apk的一个过程,必须了解Android程序开发的流程.结构.语句分支.解密原理等等. 功能 破解一个注册验证程序(自写一个简单的注册验证 ...
- Ext JS学习第四天 我们所熟悉的javascript(三)
此文用来记录学习笔记: •javascript之函数 •this关键字的使用 –this关键字总是指向调用者,谁调用函数,this就指向谁 •call.apply的使用 –call和apply主要应用 ...
- C语言结构体变量内存分配与地址对齐
地址对齐简单来说就是为了提高访问内存的速度. 数组的地址分配比较简单,由于数据类型相同,地址对齐是一件自然而然的事情. 结构体由于存在不同基本数据类型的组合,所以地址对齐存在不同情况,但总体来说有以下 ...
- excel unixtime与北京时间互转
unixtime转北京时间,在单元格内输入:=INT((B2-70*365-19)*86400-8*3600) *.要设置一下单元格格式为y-m-d h:m:s才会正确显示 北京时间转unixti ...