RPC解密--Thrift

目录

 

一、Thrift介绍

1.1 Thrift的基本工作方式

 

1.2 Thrift IDL

 

1.3 数据类型

 

二、Thrift基础架构

 

三、基本概念

3.1 协议--Protocol 支持的传输格式

3.2 传输层--Transport 支持的数据传输方式

3.3服务端类型

3.3.1 TNonblockingServer vs. THsHaServer

3.3.2 THsHaServer vs.TThreadedSelectorServer

3.3.3TThreadedSelectorServer vs. TThreadPoolServer

参考文章


​​​​​​​

一、Thrift介绍


Apache Thrift是一个有facebook开源的简单RPC框架,2007年facebook提交到Apache基金会将Thrift作为一个开源项目,现在是一个Apache的顶级项目。

根据Apache Thrift的官方描述,Thrift是一个:

software framework, for scalable cross-language services developement, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Javascript, Nodej.js, Smalltalk, OCaml and Delphi and other languages.

当时facebook创造thrift是为了解决facebook系统中各个系统之间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性。

Thrift适用于搭建大型书籍交换及存储的通用工具,对于大型系统中的内部数据传输对于JSON和XML来说,无论是性能、传输大小上都有明显的优势。

1.1 Thrift的基本工作方式

Thrift允许通过一个跨语言的定义文件的方式定义数据类型和服务接口,这个文件作为RPC客户端和服务器通信的标准,你可以去看看Thrift的白皮书了解更多的信息。

 

1.2 Thrift IDL

Thrift是IDL(interface definition language)描述性语言的一个具体实现,关于IDL的话题,我们可以追溯到CORBA(Common Object Request Broker Architecture/公用对象请求代理体系结构)盛行的1999-2001年,在IDL中我们似乎不会忘记这几个关键字:module、interface、String、long和int,我还记得IDL利用module来创建名称空间,并且准确的映射为Java的package,这些特性几乎和现在的thrift的特性完全相同,所以thrift的设计思路和理念并不是什么从火星来的new idea,看看在那个CORBA盛行的年度人们提出来的概念,CORBA请求的各个部分,和之前我们那个Thrift图是否很相似。

 

1.3 数据类型

  • Base Types: 基本类型

  • Struct: 结构体类型

  • Container: 容器类型,即List、Set、Map等

  • Exception: 异常类型

  • Service:定义对象的接口和一系列方法

 

二、Thrift基础架构

Thrift是一个服务端和客户端的架构体系,从我个人的观感上看Thrift是一个类似XML-RPC+Java-to-IDL+Serialization Tools=Thrift的东东。Thrift具有自己内部定义的传输协议规范(TProtocol)和传输数据标准(TTransports),通过IDL脚本对传输数据的数据结构(struct)和传输数据的业务逻辑(service)根据不同的运行环境快速构建相应的代码,并通过自己内部序列化机制对传输的数据进行简化和压缩提高并发、大型系统中数据交互的成本。

我们从下面的图中那个可以看到Thrift的整体架构分为6个部分:

  1. 你的业务逻辑实现(Your Code)

  2. 客户端和服务端对应的Service

  3. 执行读写操作的计算结果

  4. TProtocol

  5. TTransports

  6. 底层I/O通信

我们看图中前面三个是:

  1. 你通过Thrift脚本文件生成的代码

  2. 图中褐色部分是你根据生成代码构建的客户端和服务器的代码

  3. 红色的部分是两端产生的技术结果。

从TProtocol下面的三个部分是Thrift的传输体系和传输协议以及底层I/O通信。

Thrift并且提供阻塞、非阻塞,单线程、多线程的模式运行在服务器上,还可以配合服务器/容器一起运行,可以和现有的Java服务器/Web容器无缝的结合。\

 

如上图,客户端在进行远程方法调用时,首先是通过Thrift的编译器生成的客户端,将调用信息(方法名,参数信息)以指定的协议进行封装,而传输层TTransport是对协议层的封装进行处理(比如封装成帧frame),并通过网络发送出去。服务端这边流程跟客户端相反,收到客户端发过来的数据后,首先经过传输层对传过来的数据进行处理,然后使用特定的协议(跟客户端是一一对应的)进行解析,然后再通过生成的Processor调用用户编写的代码,如果有返回值的话,返回值以逆向的顺序,即通过协议层封装,然后传输层处理对数据进行发送,到了客户端那边就是对服务端返回的数据进行处理,使用特定协议进行解析,然后得到一个调用个的结果。

以上就是Thrift的RPC调用的一个完整流程。

 

 

三、基本概念

Thrift中的几个概念:

Server 服务模型

Handler 数据处理接口

Processor 数据处理对象

Protocol 数据传输协议

Transport 数据传输方式

Handler为抽象接口,需要在编译后的代码上自行实现。Processor调用Handler中的代码,编译自动生成,不用关心。

 

3.1 协议--Protocol 支持的传输格式

Thrift可以让你选择客户端与服务器之间的传输通信协议的类别,在传输协议上总体上划分为文本(text)和二进制(binary)传输协议,为节省带宽,提供传输效率,一般情况下使用二进制类型的传输协议为多数,但有时候还是会使用基于文本类型的协议,这些需要根据项目/产品中的实际需求:

  1. TBinaryProtocol: 二进制编码格式进行数据传输

  2. TCompactProtocol: 这种协议非常有效,使用Variable-Length Quantity(VLQ)编码对书籍进行压缩。

    代码块

    Java

    #使用 TCompactProtocol 协议构建的 Server
     TCompactProtocol.Factory proFactory = new TCompactProtocol.Factory(); 
    #使用 TCompactProtocol 协议的Client
     TCompactProtocol protocol = new TCompactProtocol(transport); 

     

  3. TJSONProtocol: 使用JSON的数据编码进行数据传输。

    代码块

    Java

    #使用 TJSONProtocol 协议构建的 Server
     TJSONProtocol.Factory proFactory = new TJSONProtocol.Factory(); 
    #使用 TJSONProtocol 协议的 client
     TJSONProtocol protocol = new TJSONProtocol(transport); 

     

  4. TSimpleJSONProtocol: 这种协议只提供JSON只写的协议,适用于通过脚本语言解析。

  5. TDebugProtocol: 在开发的过程中帮助开发人员调试使用,以文本的形式展现方便阅读。

3.2 传输层--Transport 支持的数据传输方式

  1. TSocket: 使用阻塞式I/O进行传输,也是最常见的模式

  2. TFramedTransport: 使用非阻塞方式,按块的大小进行传输,类似于Java中的NIO。

    若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型,客户端只需替换清单 TTransport 部分, TNonblockingServerTransport 类是构建非阻塞 socket 的抽象类,TNonblockingServerSocket 类继承 TNonblockingServerTransport

  3. TNonblockingTransport:使用非阻塞方式,用于构建异步客户端

  4. TFileTransport: 顾名思义按照文件的方式进行传输,虽然这种方式不提供Java的实现,但是实现起来非常简单。

  5. TmemoryTransport: 使用内存I/O,就好比Java中的ByteArrayOuputStream实现。

  6. TZibTransport: 使用只写zlib压缩,不提供Java的实现。

3.3服务端类型

  1. TSimpleServer: 单线程服务器端使用的标准的阻塞式I/O

    TSimplerServer接受一个连接,处理连接请求,直到客户端关闭了连接,它才回去接受一个新的连接。正因为它只在一个单独的线程中以阻塞I/O的方式完成这些工作,所以它只能服务一个客户端连接,其他所有客户端在被服务器端接受之前都只能等待。TSimpleServer主要用于测试目的,不要在生产环境中使用它!

  2. TThreadedServer:多线程服务模型,使用阻塞式IO,每个请求创建一个线程。

  3. TThreadPoolServer: 多线程服务器端使用标准的阻塞式I/O。

  4. TNonblockingServer: 多线程服务器端使用的非阻塞式I/O(需使用TFramedTransport数据传输方式) ,并实现了Java中的NIO通道。

 

3.3.1 TNonblockingServer vs. THsHaServer

TNonblockingServer使用非阻塞的I/O解决了TSimpleServer一个客户端阻塞其他所有客户端的问题。它使用了java.nio.channels.Selector,通过调用select(),它使得你阻塞在多个连接上,而不是阻塞在单一的连接上。当一或多个连接准备好被接受/读/写时,select()调用便会返回。TNonblockingServer处理这些连接的时候,要么接受它,要么从它那读数据,要么把数据写到它那里,然后再次调用select()来等待下一个可用的连接。通用这种方式,server可同时服务多个客户端,而不会出现一个客户端把其他客户端全部“饿死”的情况。

然而,还有个棘手的问题:所有消息是被调用select()方法的同一个线程处理的。假设有10个客户端,处理每条消息所需时间为100毫秒,那么,latency和吞吐量分别是多少?当一条消息被处理的时候,其他9个客户端就等着被select,所以客户端需要等待1秒钟才能从服务器端得到回应,吞吐量就是10个请求/秒。如果可以同时处理多条消息的话,会很不错吧?

因此,THsHaServer(半同步/半异步的server)就应运而生了。它使用一个单独的线程来处理网络I/O,一个独立的worker线程池来处理消息。这样,只要有空闲的worker线程,消息就会被立即处理,因此多条消息能被并行处理。用上面的例子来说,现在的latency就是100毫秒,而吞吐量就是100个请求/秒。

 

3.3.2 THsHaServer vs.TThreadedSelectorServer

Thrift0.8引入了另一种server实现,即TThreadedSelectorServer。它与THsHaServer的主要区别在于。TThreadedSelectorServer允许你用多个线程来处理网络I/O。它维护了两个线程池,一个用来处理网络I/O,另一个用来进行请求的处理。当网络I/O是瓶颈的时候,TThreadedSelectorServer比THsHaServer的表现要好。

 

3.3.3TThreadedSelectorServer vs. TThreadPoolServer

最后,还剩下 TThreadPoolServer。TThreadPoolServer与其他三种server不同的是:

(1)  有一个专用的线程用来接受连接。

(2)  一旦接受了一个连接,它就会被放入ThreadPoolExecutor中的一个worker线程里处理。

(3)  worker线程被绑定到特定的客户端连接上,直到它关闭。一旦连接关闭,该worker线程就又回到了线程池中。

(4)  你可以配置线程池的最小、最大线程数,默认值分别是5(最小)和Integer.MAX_VALUE(最大)。

这意味着,如果有1万个并发的客户端连接,你就需要运行1万个线程。所以它对系统资源的消耗不像其他类型的server一样那么“友好”。此外,如果客户端数量超过了线程池中的最大线程数,在有一个worker线程可用之前,请求将被一直阻塞在那里。

我们已经说过,TThreadPoolServer的表现非常优异。在我正在使用的计算机上,它可以支持1万个并发连接而没有任何问题。如果你提前知道了将要连接到你服务器上的客户端数量,并且你不介意运行大量线程的话,TThreadPoolServer对你可能是个很好的选择。

 

 

 

 

 

 

 

 

参考文章

Thrift 的原理和使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值