Table of Contentsjava
什么是Thriftc++
架构程序员
什么是RPC框架?web
Thrift的协议栈结构apache
优势服务器
建立一个Thrift服务restful
Thrift是一种接口描述语言和二进制通信协议,它被用来定义和建立跨语言的服务。它被看成一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。它经过一个代码生成引擎联合了一个软件栈,来建立不一样程度的、无缝的跨平台高效服务,可使用C#、C++(基于POSIX兼容系统)、Cappuccino、Cocoa、Delphi、Erlang、Go、Haskell、Java、Node.js、OCaml、Perl、PHP、Python、Ruby和Smalltalk。虽然它之前是由Facebook开发的,但它如今是Apache软件基金会的开源项目了。该实现被描述在2007年4月的一篇由Facebook发表的技术论文中,该论文现由Apache掌管。数据结构
https://www.jianshu.com/p/4723ce380b0e多线程
Protobuf是一个语言中立、平台中立,对结构化数据进行序列化的可扩展机制。
咱们在开发的时候开发了一个restful web service,就是基于rest的http调用,A系统做为客户端,B系统做为服务器端。A系统能够经过URL的方式携带一些数据去调用B所提供的接口而后返回相应的结果数据。这种方式咱们也能够认为是RPC的一种实现方式。对于这种方式咱们能够认为是平台独立的、语言独立的,也就是语言中立、平台中立。也就是咱们能够用Python编写的客户端去调用Java编写的服务端,由于都是经过URL的方式调用。由于URL至关于契约,URL背后的代码调用者无需关心。
RPC框架调用基本模型:如person.getPersonByName(String name),首先客户端先序列化调用数据,传给服务端,服务端再反序列化提取调用信息,查询客户端所须要的数据,完成以后再序列化结果传回给客户端。客户端再反序列化获得结果。
Apache thrift是一个可伸缩的,而且跨语言的一种服务性的开发,他所完成的功能实际上和protobuf是相似的。简单来讲,是Facebook公布的一款开源跨语言的RPC框架。
Thrift包含一套完整的栈来建立客户端和服务端程序。顶层部分是由Thrift定义生成的代码。而服务则由这个文件客户端和处理器代码生成。在生成的代码里会建立不一样于内建类型的数据结构,并将其做为结果发送。协议和传输层是运行时库的一部分。有了Thrift,就能够定义一个服务或改变通信和传输协议,而无需从新编译代码。除了客户端部分以外,Thrift还包括服务器基础设施来集成协议和传输,如阻塞、非阻塞及多线程服务器。栈中做为I/O基础的部分对于不一样的语言则有不一样的实现。
Thrift支持众多通信协议:
支持的传输协议有:
Thrift还提供众多的服务器,包括:
https://www.jianshu.com/p/4723ce380b0e
RPC全称为Remote Procedure Call,意为远程过程调用。
假设有两台服务器A,B.A服务器上部署着一个应用a,B服务器上部署着一个应用b,如今a但愿可以调用b应用的某个函数(方法),可是两者不在同一个进程内,不能直接调用,就须要经过网络传输,在AB服务器之间建一条网络传输通道,a把参数传过去,b接收到参数调用本身的方法获得结果,再经过网络传回给a。
简单讲就是A经过网络来调用B的过程,这个过程要涉及的东西不少,好比多线程、Socket、序列化反序列化、网络I/O,很复杂。因而牛掰的程序员把这些封装起来作成一套框架供你们使用,就是RPC框架。
thrift经过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,而后经过特殊的编译器来生成不一样语言的代码,以知足不一样须要的开发者。好比java开发者,就能够生成java代码,c++开发者能够生成c++代码,生成的代码中不但包含目标语言的接口定义、方法、数据类型,还包含有RPC协议层和传输层的实现代码。
Thrift是一种c/s的架构体系。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。
Thrift一些已经明确的优势包括:
Thrift由C++编写,但能够为众多语言建立代码。要建立一个Thrift服务,必须写一些Thrift文件来描述它,为目标语言生成代码,而且写一些代码来启动服务器及从客户端调用它。
Thrift将由这个描述信息生成独立的代码。例如,在Java里,PhoneType将是Phone类中一个简单的enum。
建立一个服务Hello,建立文件Hello.thrift,代码以下:
namespace java service.demo service Hello{ string helloString(1:string para) }
终端进入Hello.thrift所在目录,执行命令:
thrift -r -gen java Hello.thrift
发如今当前目录下多了一个gen-java的目录,里面的有一个Hello.java的文件。这个java文件包含Hello服务的接口定义Hello.Iface,以及服务调用的底层通讯细节,包括客户端的调用逻辑Hello.Client以及服务端的处理逻辑Hello.Processor。
建立一个Maven管理的Java项目,pom.xml中添加相关的依赖,并将Hello.java文件复制到项目中:
<dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.10.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency>
建立HelloServiceImpl实现Hello.Iface接口:
package service.demo; import org.apache.thrift.TException; public class HelloServiceImpl implements Hello.Iface { public String helloString(String para) throws TException { return "result:"+para; } }
建立服务端实现代码HelloServiceServer,把HelloServiceImpl做为一个具体的处理器传递给Thrift服务器:
public class HelloServiceServer { /** * 启动thrift服务器 */ public static void main(String[] args) { try { System.out.println("服务端开启...."); // 1.建立TProcessor TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl()); // 2.建立TserverTransport TServerSocket serverTransport = new TServerSocket(9898); // 3.建立TProtocol TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory(); TServer.Args tArgs = new TServer.Args(serverTransport); tArgs.processor(tprocessor); tArgs.protocolFactory(factory); // 4.建立Tserver,传入须要的参数,server将以上内容集成在一块儿 TServer server = new TSimpleServer(tArgs); // 5.启动server server.serve(); }catch (TTransportException e) { e.printStackTrace(); } } }
建立客户端实现代码HelloServiceClient,调用Hello.client访问服务端的逻辑实现:
public class HelloServiceClient { public static void main(String[] args) { System.out.println("客户端启动...."); TTransport transport = null; try { transport = new TSocket("localhost", 9898, 30000); // 协议要和服务端一致 TProtocol protocol = new TBinaryProtocol(transport); Hello.Client client = new Hello.Client(protocol); transport.open(); String result = client.helloString("哈哈"); System.out.println(result); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } finally { if (null != transport) { transport.close(); } } } }
所有工做完成后,下面来测试一下,先执行服务端main方法,在执行客户端main方法,会在客户端控制台打印出:哈哈
。