thrift 协议

合集下载

Thrift安装与常见错误

Thrift安装与常见错误

Thrift安装与常见错误简介Thrift是Facebook的核心技术框架之一,使不同语言开发的系统可以通过该框架进行通信。

开发者使用thrift提供的格式来定义数据和服务脚本。

thrift可以通过定义的脚本自动生成不同语言的代码以支持不同语言之间的通信。

thrift支持多种数据通信协议,比如xml,jason,binnary等等。

Thrift并不是唯一的跨语言通信框架,像google的protocol buffers也是与之类似的框架。

关于两者之前的比较可以去股沟一下。

Trift安装1.安装thrift所依赖的linux包autoconfautomakesysconftoolboostboost-devellibtoolbyacc flex bison这一步请根据相关系统进行按装,因为现在用的是red hat5服务器版,所以我直接从光盘里找rpm包直接安装通过rpm-ivh包名.rpm进行安装。

2.下载thrift的代码:/thrift/download/3.解压代码包tar -zxvf thrift-0.2.0-incubating.tar.gz4.拷贝thrift到安装目录cp -r thrift0.2.0 /usr/local/5.cd/usr/local/thrift0.2.0 运行该目录下的./bootstrap.sh shell脚本。

这一步你可能遇到这两种错误错误一[root@localhostthrift]# ./bootstrap.sh--enable-m4_pattern_allowconfigure.ac:50:error: possibly undefined macro:AC_PROG_MKDIR_PIf this token and others are legitimate,please usem4_pattern_allow.See the Autoconf documentation.configure.ac:144:error: possibly undefined macro:AC_TYPE_INT16_Tconfigure.ac:145:error: possibly undefined macro:AC_TYPE_INT32_T... ...configure.ac:155:error: possibly undefined macro:AC_TYPE_UINT8_T这个错误可以忽略,不影响使用。

Thrift基本原理与应用

Thrift基本原理与应用

Thrift基本原理与应用1 背景简介1.1什么是Thrift?Thrift是在2007 年facebook 提交Apache 基金会将Thrift 作为一个开源项目,对于当时的facebook 来说创造thrift 是为了解决facebook 系统中各系统间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性。

Thrift是一种实现RPC的软件框架,它自定义IDL,消息结构。

1.2RPC与IDLRPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。

该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。

RPC 协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。

在OSI网络通信模型中,RPC跨越了传输层和应用层。

RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

接口描述语言(Interface description language,缩写IDL),是CORBA规范的一部分,是跨平台开发的基础。

IDL是用来描述软件组件接口的一种计算机语言。

IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信交流。

1.3 为什么使用Thrift?(1)实现跨语言通信支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi等多种语言(2)完成高并发、大数据量传输(3) 使用方便,需要编写的代码较少Thrift的框架结构和原理1.4 其他实现RPC的框架和协议(1)Protocol Buffer,google公司2000年提出的RPC框架(2)Avro,Apache提出的RPC框架(3)SOAP:Simple Object Access Protocol,简单对象访问协议2 Thrift框架结构与基本原理2.1 Thrift框架结构图图 1 Thrift框架结构图2.2 TProtocolTProtocol主要负责结构化数据组装成Thrift消息结构,或者从消息结构中读出结构化数据。

分布式系统优化

分布式系统优化

分布式系统优化第一部分分布式系统的定义与特性 (2)第二部分分布式系统的架构与组件 (4)第三部分分布式系统的通信协议 (7)第四部分分布式系统的负载均衡 (10)第五部分分布式系统的容错与恢复 (13)第六部分分布式系统的性能优化 (16)第七部分分布式系统的安全与隐私保护 (19)第八部分分布式系统的发展趋势与挑战 (22)第一部分分布式系统的定义与特性分布式系统定义为:由多个节点组成的,这些节点通过网络相互通信并协同工作,以实现共同的目标。

这些节点可以独立运行,并具有自治能力,节点之间通过消息传递进行通信。

分布式系统具有以下特性:1.**分散性**:分布式系统的节点在网络中分散存在,数据和功能分布在不同的节点上。

2.**协同性**:分布式系统的各个节点通过网络相互通信,协同完成共同的目标。

3.**自治性**:每个节点都具有独立运行的能力,可以自主处理自己的任务和数据。

4.**可靠性**:分布式系统具有高可靠性,即使部分节点发生故障,整个系统仍能正常运行。

5.**可扩展性**:分布式系统可以方便地增加或减少节点,以适应不同的需求和负载。

6.**透明性**:分布式系统的节点对于用户来说是透明的,用户无需关心节点的具体位置和实现细节。

7.**容错性**:在分布式系统中,如果某个节点发生故障,其他节点可以接管该节点的任务并继续运行,以保证系统的可用性和稳定性。

8.**负载均衡**:分布式系统可以通过负载均衡技术,将任务分配到不同的节点上,以充分利用系统的资源并提高性能。

9.**可维护性**:分布式系统通常采用模块化设计,便于维护和升级。

10.**安全性**:分布式系统需要保证数据的安全性和隐私性,防止数据泄露和攻击。

总之,分布式系统是一种具有高度分散性、协同性、可靠性和可扩展性的计算系统。

它由多个节点组成,这些节点通过网络相互通信并协同工作,以实现共同的目标。

分布式系统具有许多优点,如高可靠性、可扩展性、透明性、容错性、负载均衡、可维护性和安全性等。

hbase thrift checkandput原理

hbase thrift checkandput原理

hbase thrift checkandput原理
HBase Thrift是HBase的一个API,它允许客户端使用多种编程语言(如Java、Python和Ruby)通过远程过程调用(RPC)与HBase进行交互。

CheckAndPut是HBase Thrift API的一种方法,用于检查一个给定单元格的值,并在值匹配时,将单元格的值设置为新值。

CheckAndPut方法可以接受以下参数:
-表名(Table Name):要检查和更新的表的名称。

-行键(Row Key):要检查和更新的行的行键值。

-列族(Column Family):包含要检查和更新的单元格的列族。

-列限定符(Column Qualifier):要检查和更新的单元格的列限定符。

-原值(Old Value):将要检查的单元格的旧值。

-新值(New Value):要将单元格设置为的新值。

CheckAndPut的工作原理如下:
1.客户端发出CheckAndPut命令,参数为表名、行键、列族、列限定符、要检查的旧值和要设置的新值。

2.HBase服务器处理CheckAndPut命令,并检查给定单元格的值是否
与要检查的旧值匹配。

如果匹配,则将单元格的值设置为新值并返回True;如果不匹配,则返回False。

3.客户端接收到返回结果,并可以根据需要执行其他操作。

总之,CheckAndPut方法允许客户端在并发更新数据时,使用原子操作来确保单元格的值没有被其他客户端更改。

这在许多实时和并发应用程序中非常有用。

thrift学习小结

thrift学习小结

Thrift-java学习小结Thrift是什么?什么情况下使用thriftThrift源于大名鼎鼎的facebook之手,在2007年facebook提交Apache基金会将Thrift作为一个开源项目,对于当时的facebook来说创造thrift是为了解决facebook系统中各系统间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性。

所以thrift可以支持多种程序语言,例如: C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多种不同的语言之间通信thrift可以作为二进制的高性能的通讯中间件,支持数据(对象)序列化和多种类型的RPC服务。

Thrift是IDL(interface definition language)描述性语言的一个具体实现,Thrift适用于程序对程序静态的数据交换,需要先确定好他的数据结构,他是完全静态化的,当数据结构发生变化时,必须重新编辑IDL文件,代码生成,再编译载入的流程,跟其他IDL工具相比较可以视为是Thrift的弱项,Thrift适用于搭建大型数据交换及存储的通用工具,对于大型系统中的子系统间数据传输相对于JSON和xml无论在性能、传输大小上有明显的优势。

Thrift 基础架构Thrift是一个服务端和客户端的架构体系,就是socket传输,Thrift 具有自己内部定义的传输协议规范(TProtocol)和传输数据标准(TTransports),通过IDL脚本对传输数据的数据结构(struct) 和传输数据的业务逻辑(service)根据不同的运行环境快速的构建相应的代码,并且通过自己内部的序列化机制对传输的数据进行简化和压缩提高高并发、大型系统中数据交互的成本,下图描绘了Thrift的整体架构,分为6个部分:1.你的业务逻辑实现(You Code) 2.客户端和服务端对应的Service 3.执行读写操作的计算结果4.TProtocol 5.TTransports 6.底层I/O通信Thrift脚本的数据类型* Base Types:基本类型bool Boolean, one bytebyte Signed bytei16 Signed 16-bit integeri32 Signed 32-bit integeri64 Signed 64-bit integerdouble 64-bit floating point valuestring Stringbinary Blob (byte array)* Struct:结构体类型* Container:容器类型,即List、Set、Mapmap<t1,t2> Map from one type to anotherlist<t1> Ordered list of one typeset<t1> Set of unique elements of one type* Exception:异常类型* Service:定义对象的接口,和一系列方法协议Thrift可以让你选择客户端与服务端之间传输通信协议的类别,在传输协议上总体上划分为文本(text)和二进制(binary)传输协议, 为节约带宽,提供传输效率,一般情况下使用二进制类型的传输协议为多数,但有时会还是会使用基于文本类型的协议,这需要根据项目/产品中的实际需求:* TBinaryProtocol –二进制编码格式进行数据传输。

Windows下Thrift环境搭建与示例

Windows下Thrift环境搭建与示例

Windows下Thrift环境搭建与示例目录WINDOWS下THRIFT环境搭建与示例 (1)目录 (2)1.引言 (3)2.环境搭建 (4)1.1.JAVA环境 (4)1.2.T HRIFT环境 (4)3.THRIFT的基本概念 (4)1.3.数据类型 (4)1.4.服务端编码基本步骤: (5)1.5.客户端编码基本步骤: (5)1.6.数据传输协议 (5)4.实例演示 (6)4.1.THRIFT生成代码 (6)4.1.1.创建thrift文件 (6)4.1.2.编译thrift文件 (6)4.2.代码实现 (7)4.2.1.实现服务端接口 (7)4.2.2.TSimpleServer服务端 (8)4.2.3.客户端 (9)4.3.依赖库设置 (12)4.4.运行 (12)1.引言本文档介绍windows环境下thrift的环境搭建与开发。

IDE为Eclipse,语言为Java。

Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。

它结合了功能强大的软件堆栈和代码生成引擎,以构建在C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等等编程语言间无缝结合的、高效的服务。

官网地址:参考:/soa/rpc/thrift-sample//jnb/jnbJun2009.html/thrift/static/files/thrift-20070401.pdf/search-engine/thrift-for-windows//search-engine/thrift-rpc/2.环境搭建1.1.java环境下载JDK和ANT,并且配置环境变量。

测试是否配置成功,如下:下载安装Eclipse,用于java程序的开发。

1.2.Thrift环境下载Thrift: /download解压thrift-0.9.1.tar.gz,复制到C盘。

thrift 开发教程

thrift 开发教程

1 编写thrift文件(如aa.thrift)namespace java 189.uc.thriftnamespace cppthrift.vdbnamespace rbthrift.vdbnamespace perlthrift.vdbnamespace csharpthrift.vdbnamespace jsthrift.vdbnamespace stthrift.vdbnamespace pythrift.vdbnamespace php thriftserviceUCThriftService{string ucOperator(1:string actionType, 2:string uid, 3:string data),}2 生成java文件thrift-0.6.0.exe -r --gen java uc.thriftthrift-0.6.0.exe -r --gen java uc.thriftthrift-0.6.0.exe -r --gen phpuc.thriftthrift-0.6.0.exe -r --gen pyuc.thrift可以生成php,py等等的3 服务端编写1)实现UCThriftService.Ifacepublic class UCThriftServiceImpl implements UCThriftService.Iface {public static Logger logger = Logger.getLogger(UCThriftServiceImpl.class);@Overridepublic String ucOperator(String actionType, String suid, String data)throws TException {System.out.println("test");}}2)运行的main编写public class UCServiceServer {private static Logger logger = Logger.getLogger(UCServiceServer.class);public static void main(String... args) throws Exception {//这个是用properties编写的,可以自行决定String server = PropertiesUtil.getValue("tserver.properties","ucserver.nio","hahs"); if ("nio".equalsIgnoreCase(server)) {startNIO();} if ("hahs".equalsIgnoreCase(server)) {startHAHS();} else {start();}}private static void start() throws TTransportException {String address = PropertiesUtil.getValue("tserver.properties","ucserver.address","0.0.0.0");int port = Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.port","5555")); intclientTimeout =Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.clientTimeout","30000")); intminWorkerThreads =Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.minWorkerThreads","25")); intmaxWorkerThreads =Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.maxWorkerThreads","25")); String protocol = PropertiesUtil.getValue("tserver.properties","ucserver.protocol","binary"); TServerSocket socket = new TServerSocket(new InetSocketAddress(address,port), clientTimeout);UCThriftService.Processor process = new UCThriftService.Processor(UCThriftServiceImpl.instance());TThreadPoolServer.Argsarg = new TThreadPoolServer.Args(socket);if("compact".equalsIgnoreCase(protocol)){arg.protocolFactory(new TCompactProtocol.Factory());}else if("binary".equalsIgnoreCase(protocol)){arg.protocolFactory(new TBinaryProtocol.Factory());}else{arg.protocolFactory(new TBinaryProtocol.Factory());}arg.transportFactory(new TFramedTransport.Factory());arg.maxWorkerThreads(maxWorkerThreads);arg.minWorkerThreads(minWorkerThreads);// arg.processor(process);arg.processorFactory(new TProcessorFactory(process));TServer server = new TThreadPoolServer(arg);Logger.getLogger(UCServiceServer.class).info(UCServiceServer.class.getSimpleName() + " Listen at " + port);while(true){try {server.serve();} catch (Exception e) {logger.error(e.getMessage(),e);server.stop();Logger.getLogger(UCServiceServer.class).info(UCServiceServer.class.getSimpleName() + " Reload");server = new TThreadPoolServer(arg);}}}private static void startNIO() throws TTransportException {String address = PropertiesUtil.getValue("tserver.properties","ucserver.address","0.0.0.0");int port = Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.port","5555")); intclientTimeout =Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.clientTimeout","30000")); String protocol = PropertiesUtil.getValue("tserver.properties","ucserver.protocol","binary"); TNonblockingServerSocket socket = new TNonblockingServerSocket(new InetSocketAddress(address, port), clientTimeout);UCThriftService.Processor process = new UCThriftService.Processor( UCThriftServiceImpl.instance());TNonblockingServer.Argsarg = new TNonblockingServer.Args(socket);if("compact".equalsIgnoreCase(protocol)){arg.protocolFactory(new TCompactProtocol.Factory());}else if("binary".equalsIgnoreCase(protocol)){arg.protocolFactory(new TBinaryProtocol.Factory());}else{arg.protocolFactory(new TBinaryProtocol.Factory());}arg.transportFactory(new TFramedTransport.Factory());// arg.processor(process);arg.processorFactory(new TProcessorFactory(process));TServer server = new TNonblockingServer(arg);Logger.getLogger(UCServiceServer.class).info("NIO " + UCServiceServer.class.getSimpleName() + " Listen at "+ port);while(true){try {server.serve();} catch (Exception e) {server.stop();Logger.getLogger(UCServiceServer.class).info("NIO " + UCServiceServer.class.getSimpleName() + " Reload");server = new TNonblockingServer(arg);}}}private static void startHAHS() throws TTransportException {String address = PropertiesUtil.getValue("tserver.properties","ucserver.address","0.0.0.0");int port = Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.port","5555")); intclientTimeout =Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.clientTimeout","30000")); intminWorkerThreads =Integer.parseInt(PropertiesUtil.getValue("tserver.properties","ucserver.minWorkerThreads","25")); String protocol = PropertiesUtil.getValue("tserver.properties","ucserver.protocol","binary");TNonblockingServerSocket socket = new TNonblockingServerSocket(new InetSocketAddress(address, port), clientTimeout);UCThriftService.Processor process = new UCThriftService.Processor(UCThriftServiceImpl.instance());THsHaServer.Argsarg = new THsHaServer.Args(socket);if("compact".equalsIgnoreCase(protocol)){arg.protocolFactory(new TCompactProtocol.Factory());}else if("binary".equalsIgnoreCase(protocol)){arg.protocolFactory(new TBinaryProtocol.Factory());}else{arg.protocolFactory(new TBinaryProtocol.Factory());}arg.transportFactory(new TFramedTransport.Factory());arg.workerThreads(minWorkerThreads);// arg.processor(process);arg.processorFactory(new TProcessorFactory(process));TServer server = new THsHaServer(arg);Logger.getLogger(UCServiceServer.class).info("HAHS " + UCServiceServer.class.getSimpleName() + " Listen at "+ port);while(true){try {server.serve();} catch (Exception e) {logger.error(e.getMessage(),e);server.stop();Logger.getLogger(UCServiceServer.class).info("HAHS " + UCServiceServer.class.getSimpleName() + " Reload");server = new TNonblockingServer(arg);}}}}4 客户端编写public void newThread() throws TException {String address = "0.0.0.0";int port = 5555;intclientTimeout = 30000;TTransport transport = new TFramedTransport(new TSocket(address, port, clientTimeout));TProtocol protocol = new TBinaryProtocol(transport);UCThriftService.Client client = new UCThriftService.Client(protocol); transport.open();try {long bt = System.currentTimeMillis();System.out.println(URLDecoder.decode(client.ucOperator("get", "29", "")));} catch (TApplicationException e) {System.out.println(e.getMessage() + " " + e.getType());}transport.close();}5运行先运行ucserverclient连接可在控制台看到输出说明:client连服务端有几个要注意的地方:1 服务器的ip和端口2 服务端和客户端用的transport 和协议一定要一样比如:如果服务端用的TFrameTransport那客户端也要用TFrameTransport 如果服务端用的TBinaryProtocol,那客户端也要用TBinaryProtocol否则会出一个好像是TTransportException的一个异常。

thrift简单示例(基于C++)

thrift简单示例(基于C++)

thrift简单⽰例(基于C++)这个thrift的简单⽰例, 来源于官⽹ (/tutorial/cpp), 因为我觉得官⽹的例⼦已经很简单了, 所以没有写新的⽰例, 关于安装的教程, 可以参考https:///albizzia/p/10838646.html, 关于thrift⽂件的语法, 可以参考: https:///albizzia/p/10838646.html.thrift⽂件⾸先给出shared.thrift⽂件的定义:/*** 这个Thrift⽂件包含⼀些共享定义*/namespace cpp sharedstruct SharedStruct {1: i32 key2: string value}service SharedService {SharedStruct getStruct(1: i32 key)}然后给出tutorial.thrift的定义:/*** Thrift引⽤其他thrift⽂件, 这些⽂件可以从当前⽬录中找到, 或者使⽤-I的编译器参数指⽰.* 引⼊的thrift⽂件中的对象, 使⽤被引⼊thrift⽂件的名字作为前缀, 例如shared.SharedStruct.*/include "shared.thrift"namespace cpp tutorial// 定义别名typedef i32 MyInteger/*** 定义常量. 复杂的类型和结构体使⽤JSON表⽰法.*/const i32 INT32CONSTANT = 9853const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}/*** 枚举是32位数字, 如果没有显式指定值,从1开始.*/enum Operation {ADD = 1,SUBTRACT = 2,MULTIPLY = 3,DIVIDE = 4}/*** 结构体由⼀组成员来组成, ⼀个成员包括数字标识符, 类型, 符号名, 和⼀个可选的默认值.* 成员可以加"optional"修饰符, ⽤来表明如果这个值没有被设置, 那么他们不会被串⾏化到* 结果中. 不过这个在有些语⾔中, 需要显式控制.*/struct Work {1: i32 num1 = 0,2: i32 num2,3: Operation op,4: optional string comment,}// 结构体也可以作为异常exception InvalidOperation {1: i32 whatOp,2: string why}/*** 服务需要⼀个服务名, 加上⼀个可选的继承, 使⽤extends关键字*/service Calculator extends shared.SharedService {/** * ⽅法定义和C语⾔⼀样, 有返回值, 参数或者⼀些它可能抛出的异常, 参数列表和异常列表的 * 写法与结构体中的成员列表定义⼀致. */void ping(),i32 add(1:i32 num1, 2:i32 num2),i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),/** * 这个⽅法有oneway修饰符, 表⽰客户段发送⼀个请求, 然后不会等待回应. Oneway⽅法 * 的返回值必须是void */oneway void zip()}将上述⽂件放置在同⼀个⽂件夹, 然后编译上述的thrift⽂件:$ thrift -r --gen cpp tutorial.thrift⽣成的⽂件会出现在gen-cpp⼦⽂件夹中, 因为编译时使⽤了-r参数, 所以shared.thrift也会被编译.我们可以考虑查看⼀下thrift编译之后⽣成的⽂件, 这⾥, 我们可以考虑先编译shared.thrift, 编译后, 会⽣成7个⽂件, 分别是shared_constants.h, shared_constants.cpp, shared_types.h, shared_types.cpp, SharedService.h, SharedService.cpp, SharedService_server.skeleton.cpp.我们先查看shared_constants.h和shared.constants.cpp, 这两个⽂件的命名是原先的thrift⽂件名, 加上_constants, 换种⽅式说, 就是xxx.thrift会⽣成xxx_constants.h和xxx_constants.cpp. 查看⼀下这两个⽂件中的内容: 其中会有⼀个类叫做xxxConstants, 在这个类中, 会将常量作为公有成员, 然后可以通过⼀个全局变量g_xxx_constants 访问. ⽽xxx_constants.cpp为类函数的定义, 以及全局变量的定义, 应该⽐较容易理解.关于shared_types.h和shared_types.cpp⽂件, 查看shared_types.h中的内容可以看出, shared_types.h中是thrift⽂件中各种类型的定义, 这个根据⽂件名应该可以⼤致猜出. 其中每⼀个结构体对应两部分, 假设这个结构体叫yyy, 那么第⼀个部分是结构体_yyy__isset,这个结构体会为thrift中yyy的每个字段添加⼀个对应的bool值, 名字相同.第⼆部分是结构体yyy. 这个结构体中包括thrift中yyy的每个字段, 加上_yyy__isset对象. 这个对象⽤于yyy读取输⼊给⾃⾝赋值时, 标识某个字段是否被赋值. yyy中的函数主要有如下⼏个: (1) 默认构造函数 (2) 析构函数 (3) 设置成员变量值的函数 (4) ⽐较函数 (5) read函数, ⽤来读取TProtocol对象的内容, 来给⾃⼰赋值 (6) write函数, 将⾃⾝的值写⼊到TProtocol的对象中. 最后还有⼀个swap函数.关于SharedService.h和SharedService.cpp⽂件, 查看SharedService.h中的内容可以看出, 这个⽂件的⽂件名来⾃于thrift中的service SharedService, 假设服务名叫做zzz, 那么就会⽣成对应的zzz.h和zzz.cpp⽂件, ⽤来实现这个服务的接⼝相关的内容. 查看SharedService.h⽂件, 可以看到如下内容:(1) class SharedServiceIf⽤来实现thrift⽂件中SharedService的接⼝,(2) SharedServiceIfFactory⽤来实现SharedServiceIf的⼯⼚接⼝, 构建函数为getHandler, 释放函数为releaseHandler, 其中SharedServiceIf在⼯⼚类中定义别名Handler.(3) SharedServiceIfSingletonFactory是SharedServiceIfFactory的⼀个具体实现, ⽤来实现返回单例的SharedServiceIf对象.(4) SharedServiceNull是SharedServiceIf的不做任何⾏为的实现.(5) _SharedService_getStruct_args__isset是SharedService服务的getStruct函数的参数对应的isset类, ⽤来表⽰这些参数是否存在.(6) SharedService_getStruct_args是SharedService服务的getStruct函数的参数对应的类, ⽤来表⽰⼀个服务的函数的参数, 实现内容和thrift⽂件中的结构体的实现基本⼀致.(7) SharedService_getStruct_pargs⽤处不太清楚.(8) _SharedService_getStruct_result__isset是SharedService服务的getStruct函数的返回值对应的isset函数, ⽤来表⽰返回值是否设置.(9) SharedService_getStruct_result是SharedService服务的getStruct函数的返回值对应的类, ⽤来表⽰⼀个服务的函数的返回值.(10) _SharedService_getStruct_presult__isset和SharedService_getStruct_presult⽤处不太清楚.(11) SharedServiceClient 是thrift中SharedService服务的客户端实现. SharedServiceClient包括以下内容: 1) 构造函数 2) 获取输⼊和输出Protocol的函数 3) 服务中定义的⽅法, 这⾥是getStruct函数, 以及getStruct函数实现的两个函数, void SharedServiceClient::getStruct(SharedStruct& _return, const int32_t key) { send_getStruct(key); recv_getStruct(_return); } (12) SharedServiceProcessor为编译器⾃动⽣成的对象, 位于Protocol层之上, Server层之下, 实现从输⼊protocol中读取数据, 然后交给具体的Handler处理, 然后再将结果写⼊到输出protocol中. 关于这些联系可以参考 https:///albizzia/p/10884907.html. (13) SharedServiceProcessorFactory是SharedServiceProcessor的⼯⼚类. (14) SharedServiceMultiface是SharedServiceIf的具体实现, 实现了类似于chain of responsiblity的效果, 也就是依次调⽤构造函数中传⼊的多个SharedServiceIf对象的对应⽅法. 参考代码:void getStruct(SharedStruct& _return, const int32_t key) {size_t sz = ifaces_.size();size_t i = 0;for (; i < (sz - 1); ++i) {ifaces_[i]->getStruct(_return, key);}ifaces_[i]->getStruct(_return, key);return;}关于SharedService_server.skeleton.cpp⽂件, 假设thrift中定义的服务名叫做zzz, 那么这个⽂件名叫做zzz_server.skeleton.cpp, skeleton的含义是框架, 这个⽂件的作⽤是告诉我们如何写出thrift服务器的代码. 这个⽂件包括两部分:(1) 类SharedServiceHandler, 这个类⽤来实现SharedServiceIf, 假设thrift中的服务名叫做zzz, 那么这个类的名字就相对的叫做zzzHandler. 这个类会给出如果你想要实现SharedServiceIf, 那么你需要实现的具体的函数, 对于这个类来说, 需要实现构造函数和getStruct函数, getStruct函数是服务中定义的函数, 有时候, 你也需要实现析构函数吧.(2) 然后是⼀个main函数, main函数中的内容, 告诉你怎样实现⼀个简单的thrift服务器. 你可以考虑把这个⽂件拷贝⼀份, 然后根据这个拷贝进⾏修改, 实现服务器的功能.如果把shared.thrift和tutorial.thrift⼀起编译, 那么就会出现14个⽂件, 每个thrift⽂件对应7个, ⽂件的布局和作⽤和之前说明的⼀致.服务端代码#include <thrift/concurrency/ThreadManager.h>#include <thrift/concurrency/PlatformThreadFactory.h>#include <thrift/protocol/TBinaryProtocol.h>#include <thrift/server/TSimpleServer.h>#include <thrift/server/TThreadPoolServer.h>#include <thrift/server/TThreadedServer.h>#include <thrift/transport/TServerSocket.h>#include <thrift/transport/TSocket.h>#include <thrift/transport/TTransportUtils.h>#include <thrift/TToString.h>#include <thrift/stdcxx.h>#include <iostream>#include <stdexcept>#include <sstream>#include "../gen-cpp/Calculator.h"using namespace std;using namespace apache::thrift;using namespace apache::thrift::concurrency;using namespace apache::thrift::protocol;using namespace apache::thrift::transport;using namespace apache::thrift::server;using namespace tutorial;using namespace shared;class CalculatorHandler : public CalculatorIf {public:CalculatorHandler() {}void ping() { cout << "ping()" << endl; }int32_t add(const int32_t n1, const int32_t n2) {cout << "add(" << n1 << ", " << n2 << ")" << endl;return n1 + n2;}int32_t calculate(const int32_t logid, const Work& work) {cout << "calculate(" << logid << ", " << work << ")" << endl;int32_t val;switch (work.op) {case Operation::ADD:val = work.num1 + work.num2;break;case Operation::SUBTRACT:val = work.num1 - work.num2;break;case Operation::MULTIPLY:val = work.num1 * work.num2;break;case Operation::DIVIDE:if (work.num2 == 0) {InvalidOperation io;io.whatOp = work.op;io.why = "Cannot divide by 0";throw io;}val = work.num1 / work.num2;break;default:InvalidOperation io;io.whatOp = work.op;io.why = "Invalid Operation";throw io;}SharedStruct ss;ss.key = logid;ss.value = to_string(val);log[logid] = ss;return val;}void getStruct(SharedStruct& ret, const int32_t logid) {cout << "getStruct(" << logid << ")" << endl;ret = log[logid];}void zip() { cout << "zip()" << endl; }protected:map<int32_t, SharedStruct> log;};/*CalculatorIfFactory is code generated.CalculatorCloneFactory is useful for getting access to the server side of thetransport. It is also useful for making per-connection state. Without thisCloneFactory, all connections will end up sharing the same handler instance.*/class CalculatorCloneFactory : virtual public CalculatorIfFactory {public:virtual ~CalculatorCloneFactory() {}virtual CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo){stdcxx::shared_ptr<TSocket> sock = stdcxx::dynamic_pointer_cast<TSocket>(connInfo.transport);cout << "Incoming connection\n";cout << "\tSocketInfo: " << sock->getSocketInfo() << "\n";cout << "\tPeerHost: " << sock->getPeerHost() << "\n";cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n";cout << "\tPeerPort: " << sock->getPeerPort() << "\n";return new CalculatorHandler;}virtual void releaseHandler( ::shared::SharedServiceIf* handler) {delete handler;}};int main() {TThreadedServer server(stdcxx::make_shared<CalculatorProcessorFactory>(stdcxx::make_shared<CalculatorCloneFactory>()), stdcxx::make_shared<TServerSocket>(9090), //portstdcxx::make_shared<TBufferedTransportFactory>(),stdcxx::make_shared<TBinaryProtocolFactory>());/*// if you don't need per-connection state, do the following insteadTThreadedServer server(stdcxx::make_shared<CalculatorProcessor>(stdcxx::make_shared<CalculatorHandler>()),stdcxx::make_shared<TServerSocket>(9090), //portstdcxx::make_shared<TBufferedTransportFactory>(),stdcxx::make_shared<TBinaryProtocolFactory>());*//*** Here are some alternate server types...// This server only allows one connection at a time, but spawns no threadsTSimpleServer server(stdcxx::make_shared<CalculatorProcessor>(stdcxx::make_shared<CalculatorHandler>()),stdcxx::make_shared<TServerSocket>(9090),stdcxx::make_shared<TBufferedTransportFactory>(),stdcxx::make_shared<TBinaryProtocolFactory>());const int workerCount = 4;stdcxx::shared_ptr<ThreadManager> threadManager =ThreadManager::newSimpleThreadManager(workerCount);threadManager->threadFactory(stdcxx::make_shared<PlatformThreadFactory>());threadManager->start();// This server allows "workerCount" connection at a time, and reuses threadsTThreadPoolServer server(stdcxx::make_shared<CalculatorProcessorFactory>(stdcxx::make_shared<CalculatorCloneFactory>()), stdcxx::make_shared<TServerSocket>(9090),stdcxx::make_shared<TBufferedTransportFactory>(),stdcxx::make_shared<TBinaryProtocolFactory>(),threadManager);*/cout << "Starting the server..." << endl;server.serve();cout << "Done." << endl;return0;}上述代码应该很容易理解, 在这⾥就不解释了.客户端代码#include <iostream>#include <thrift/protocol/TBinaryProtocol.h>#include <thrift/transport/TSocket.h>#include <thrift/transport/TTransportUtils.h>#include <thrift/stdcxx.h>#include "../gen-cpp/Calculator.h"using namespace std;using namespace apache::thrift;using namespace apache::thrift::protocol;using namespace apache::thrift::transport;using namespace tutorial;using namespace shared;int main() {stdcxx::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));stdcxx::shared_ptr<TTransport> transport(new TBufferedTransport(socket));stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));CalculatorClient client(protocol);try {transport->open();client.ping();cout << "ping()" << endl;cout << "1 + 1 = " << client.add(1, 1) << endl;Work work;work.op = Operation::DIVIDE;work.num1 = 1;work.num2 = 0;try {client.calculate(1, work);cout << "Whoa? We can divide by zero!" << endl;} catch (InvalidOperation& io) {cout << "InvalidOperation: " << io.why << endl;// or using generated operator<<: cout << io << endl;// or by using std::exception native method what(): cout << io.what() << endl;}work.op = Operation::SUBTRACT;work.num1 = 15;work.num2 = 10;int32_t diff = client.calculate(1, work);cout << "15 - 10 = " << diff << endl;// Note that C++ uses return by reference for complex types to avoid// costly copy constructionSharedStruct ss;client.getStruct(ss, 1);cout << "Received log: " << ss << endl;transport->close();} catch (TException& tx) {cout << "ERROR: " << tx.what() << endl;}}从上⾯的客户端调⽤来看, ⽅法调⽤和本地的类对象的调⽤很相似, thrift的设计算是很巧妙的. ⾥⾯的代码应该不复杂, 所以也不进⾏具体的讲解了.查看⼀下CMakeLists.txt⽂件:cmake_minimum_required(VERSION 2.8)#include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")#Make sure gen-cpp files can be includedinclude_directories("${CMAKE_CURRENT_BINARY_DIR}")include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp")include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src")set(tutorialgencpp_SOURCESgen-cpp/Calculator.cppgen-cpp/SharedService.cppgen-cpp/shared_constants.cppgen-cpp/shared_types.cppgen-cpp/tutorial_constants.cppgen-cpp/tutorial_types.cpp)add_library(tutorialgencpp STATIC ${tutorialgencpp_SOURCES})target_link_libraries(tutorialgencpp thrift)add_custom_command(OUTPUT gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp COMMAND ${THRIFT_COMPILER} --gen cpp -r ${PROJECT_SOURCE_DIR}/tutorial/tutorial.thrift)add_executable(TutorialServer CppServer.cpp)target_link_libraries(TutorialServer tutorialgencpp)if (ZLIB_FOUND)target_link_libraries(TutorialServer ${ZLIB_LIBRARIES})endif ()add_executable(TutorialClient CppClient.cpp)target_link_libraries(TutorialClient tutorialgencpp)if (ZLIB_FOUND)target_link_libraries(TutorialClient ${ZLIB_LIBRARIES})endif ()编译运⾏, 我这边启动客户端和服务端的命令分别是:$ LD_LIBRARY_PATH=/usr/local/lib ./TutorialServer$ LD_LIBRARY_PATH=/usr/local/lib ./TutorialClient注: 上述代码可以在thrift源代码中的tutorial/cpp⽂件夹找到.。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

thrift 协议
Thrift 协议是一种跨语言的远程过程调用 (RPC) 框架,由Facebook 开发并开源。

它是一种二进制的协议,旨在解决不
同编程语言之间的通信问题。

本文将介绍 Thrift 协议的特点、
使用场景、以及一些实际应用案例。

首先,Thrift 协议具有跨语言的特性。

它支持多种编程语言,
包括 Java、Python、C++、C#、Go 等,因此可以实现不同语
言之间的通信和数据交换。

这种特性使得 Thrift 协议在分布式
系统中非常有用,可以实现不同语言的服务间相互调用。

其次,Thrift 协议是一种二进制的协议。

相比于文本协议如XML 或 JSON,二进制协议具有更小的体积和更高的性能。

Thrift 协议使用二进制编码来序列化和反序列化数据,提高了
数据传输的效率,尤其在网络传输中表现优异。

使用 Thrift 协议的场景非常广泛。

首先,它可以用于构建分布
式系统中的服务间通信。

例如,一个后端服务使用Java 编写,而另一个前端服务使用 Python 编写,它们可以通过 Thrift 协
议进行通信。

这样,不同服务之间可以方便地传递数据和调用函数。

其次,Thrift 协议也适合用于构建高性能的数据存储和传输系统。

通过使用 Thrift 协议,可以将数据序列化为紧凑的二进制
格式,从而减少存储空间和网络带宽的消耗。

这在大规模的数据处理和分析场景中尤为重要,能够提高系统的吞吐量和响应速度。

在实际应用中,有很多成功的案例使用了 Thrift 协议。

例如,Twitter 的分布式消息队列系统 Apache Kafka 就是使用 Thrift 协议进行服务间通信。

Kakfa 的生产者和消费者可以使用不同编程语言实现,它们通过 Thrift 协议进行数据交换和通信。

另一个例子是 Airbnb 的分布式任务队列系统 Airflow。

Airflow 采用了 Thrift 协议进行不同服务之间的通信,可以方便地将数据和任务派发给各个服务节点。

这样,Airflow 实现了高效的任务调度和分布式计算。

总而言之,Thrift 协议是一种适用于跨语言通信和数据交换的二进制协议。

它具有高性能、低带宽消耗的特性,在分布式系统和大规模数据处理场景中得到了广泛应用。

通过使用 Thrift 协议,不同编程语言之间可以方便地进行通信和协作,提高系统的可扩展性和灵活性。

相关文档
最新文档