现现在对于任何一个大型的服务,都不太多是一个单体的服务。而是由诸多的子服务构成,具体的业务逻辑经过子服务之间的相互调用来完成。这种相互的调用称之为远程调用,也就是一般所说的 RPC。java
RPC(Remote Procedure Call)是指远程调用,这个和本地调用有很大的区别。下面在 main
方法中调用 helloWorld
就是本地调用。apache
public class Main {
public static void final main(String[] args) {
helloWorld(); // 本地调用
}
public static void helloWorld() {
System.out.println("Hello World");
}
}
复制代码
如今假设 helloWorld
这个方法不在本地,无法直接调用,那么就须要经过远程调用来访问这个方法,在进行远程调用的过程当中,就产生了客户端-服务端(Server-Client)模式,服务的提供方就是服务端,服务的调用方就是客户端,客户端和服务端并非绝对不变的,要看具体的服务的调用流程来认定服务端和客户端。编程
远程调用的方式有不少,好比 Java 中的 RMI(Remote Method Invocation) 就是典型的 RPC, 还有 Http 也能够认为是一种 RPC。服务器
Thrift 是 FaceBook 实现的一种支持多语言的 RPC 框架,对于主流的编程语言 Java
,C++
, Python
等都有很好的支持。 Thrift 会经过自身的 IDL(Interface Description Language)
语言来对接口进行定义,而后 Thrift 经过定义好的 IDL 文件生成相应的接口脚手架,而后只须要分别实现接口脚手架的 Server 端和 Client 端。并将 Server 端进行部署,Client 就能够访问 Server端的服务。网络
下图是 Thrift 官方给出的架构图。Thrift 支持的语言多达 28 种,对于各种操做系统也都提供了支持,Thrift 将自身划为4层(不要和网络的四层协议混淆),并且对于各个层已经作好干净的分层和实现。对于不一样的业务场景就能够选择不一样的协议进行组合。数据结构
Thrift 总体上能够分红如下四层:架构
Thrift 的性能在现有的 RPC 框架中属于前列,这里有详细的 Benchmark,若是特别关注性能,那么 Thrift 是一个很好的选择。并发
并且 Thrift 提供了多种网络模型,支持阻塞服务模型和非阻塞服务模型,全部的网络处理模型都继承自 TServer。框架
阻塞服务模型:异步
非阻塞服务模型:
数据在网络的传输过程当中,序列化和反序列化是一个很重要的过程,对于不一样的系统,对序列化有着不一样的要求,Thrift 提供了多种序列化的方式来知足不一样的要求。传输协议整体上能够分红文本和二进制的两种协议。
Thrift 有以下的传输协议:
Thrift 的安装在官方文档已经介绍的很清楚了。
Thrift 使用 IDL 来定义(Client-Server)之间的接口。假如须要定义一个 hello 的接口,那么就能够定义一个 hello.thrift
文件,文件的内容以下:
service HelloWorldService {
string hello(1: string name)
}
复制代码
上面定义了一个名为 HelloWorldService
的服务,在这个服务器中有一个叫 hello
的接口,这个接口接受一个 string
类型的参数。
service
和 string
都是 IDL 的关键字,IDL 中的关键字包括:
这些都是 IDL 的基本数据结构,也还有命名空间、异常、常量等关键字。完整的 IDL文档看这里
上面的 IDL 代码定义好了一个 Thrift 接口的规则,Thrift 就能够根据这个规则生成相应的接口文件。经过这些接口文件,就能够方便的实现相应的业务逻辑,至关于 Thrift 经过 IDL 文件搭出了服务脚手架。
在生成的脚手架文件中,有两个 interface 很是重要:
AsyncIface
和 AsyncClient
是这两个 interface 的异步版本。
下面使用 SimpleServer
来实现这个服务:
Iface 实现:
public class HelloWorldServiceImpl implements HelloWorldService.Iface{
@Override
public String say(String username) throws TException {
return "Hello " + username;
}
}
/** *建立一个服务器,向外暴露服务 */
public class HelloWorldServer {
public static void main(String[] args) throws TTransportException {
TServerSocket serverSocket = new TServerSocket(9090);
HelloWorldService.Processor processor = new HelloWorldService.Processor(new HelloWorldServiceImpl());
TSimpleServer.Args tArgs = new TSimpleServer.Args(serverSocket);
tArgs.processor(processor);
TServer server = new TSimpleServer(tArgs);
server.serve();
}
}
复制代码
Client实现
/** * 客户端,链接服务器,而且发送消息 */
public class HelloWorldClient {
public static void main(String[] args) throws TTransportException, TException {
TTransport transport = new TSocket("127.0.0.1", 9090, 3000);
TProtocol protocol = new TBinaryProtocol(transport);
HelloWorldService.Client client = new HelloWorldService.Client(protocol);
try {
transport.open();
String result = client.say("Ray");
System.out.println(result);
} finally {
if (null != transport) {
transport.close();
}
}
}
}
复制代码
一个简单的 Thrift 的服务也就实现了。
(完)