一:概念
Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等等编程语言间无缝结合的、高效的服务。
二:过程
(1)通过IDL(接口描述语言)定义一个接口的thrift文件,然后通过thrift的多语言编译功能,将接口定义的thrift文件翻译成对应的语言版本的接口文件;
(2) Thrift生成的特定语言的接口文件中包括客户端部分和服务器部分;
(3)客户端通过接口文件中的客户端部分生成一个Client对象,这个客户端对象中包含所有接口函数的存根实现,然后用户代码就可以通过这个Client对象来调用thrift文件中的那些接口函数了,但是,客户端调用接口函数时实际上调用的是接口函数的本地存根实现,如图3.2中的箭头1所示;
(4)接口函数的存根实现将调用请求发送给thrift服务器端,然后thrift服务器根据调用的函数名和函数参数,调用实际的实现函数来完成具体的操作,如图3.2中的箭头2所示;
(5)Thrift服务器在完成处理之后,将函数的返回值发送给调用的Client对象;如图3.2中的箭头3所示;
(6) Thrift的Client对象将函数的返回值再交付给用户的调用函数,如图3.2中的箭头4所示;
图3.2 thrift的RPC调用过程
三: Thrift源码分析
源码分析主要分析thrift生成的java接口文件,并以TestThriftService.java为例,以该文件为线索,逐渐分析文件中遇到的其他类和文件;在thrift生成的服务接口文件中,共包含以下几部分:
(1)异步客户端类AsyncClient和异步接口AsyncIface,本节暂不涉及这些异步操作相关内容;
(2)同步客户端类Client和同步接口Iface,Client类继承自TServiceClient,并实现了同步接口Iface;Iface就是根据thrift文件中所定义的接口函数所生成;Client类是在开发Thrift的客户端程序时使用,Client类是Iface的客户端存根实现, Iface在开发Thrift服务器的时候要使用,Thrift的服务器端程序要实现接口Iface。
(3)Processor类,该类主要是开发Thrift服务器程序的时候使用,该类内部定义了一个map,它保存了所有函数名到函数对象的映射,一旦Thrift接到一个函数调用请求,就从该map中根据函数名字找到该函数的函数对象,然后执行它;
(4)参数类,为每个接口函数定义一个参数类,例如:为接口getInt产生一个参数类:getInt_args,一般情况下,接口函数参数类的命名方式为:接口函数名_args;
(5)返回值类,每个接口函数定义了一个返回值类,例如:为接口getInt产生一个返回值类:getInt_result,一般情况下,接口函数返回值类的命名方式为:接口函数名_result;
参数类和返回值类中有对数据的读写操作,在参数类中,将按照协议类将调用的函数名和参数进行封装,在返回值类中,将按照协议规定读取数据。
Thrift调用过程中,Thrift客户端和服务器之间主要用到传输层类、协议层类和处理类三个主要的核心类,这三个类的相互协作共同完成rpc的整个调用过程。在调用过程中将按照以下顺序进行协同工作:
(1) 将客户端程序调用的函数名和参数传递给协议层(TProtocol),协议层将函数名和参数按照协议格式进行封装,然后封装的结果交给下层的传输层。此处需要注意:要与Thrift服务器程序所使用的协议类型一样,否则Thrift服务器程序便无法在其协议层进行数据解析;
(2) 传输层(TTransport)将协议层传递过来的数据进行处理,例如传输层的实现类TFramedTransport就是将数据封装成帧的形式,即“数据长度+数据内容”,然后将处理之后的数据通过网络发送给Thrift服务器;此处也需要注意:要与Thrift服务器程序所采用的传输层的实现类一致,否则Thrift的传输层也无法将数据进行逆向的处理;
(3) Thrift服务器通过传输层(TTransport)接收网络上传输过来的调用请求数据,然后将接收到的数据进行逆向的处理,例如传输层的实现类TFramedTransport就是将“数据长度+数据内容”形式的网络数据,转成只有数据内容的形式,然后再交付给Thrift服务器的协议类(TProtocol);
(4) Thrift服务端的协议类(TProtocol)将传输层处理之后的数据按照协议进行解封装,并将解封装之后的数据交个Processor类进行处理;
(5) Thrift服务端的Processor类根据协议层(TProtocol)解析的结果,按照函数名找到函数名所对应的函数对象;
(6) Thrift服务端使用传过来的参数调用这个找到的函数对象;
(7) Thrift服务端将函数对象执行的结果交给协议层;
(8) Thrift服务器端的协议层将函数的执行结果进行协议封装;
(9) Thrift服务器端的传输层将协议层封装的结果进行处理,例如封装成帧,然后发送给Thrift客户端程序;
(10) Thrift客户端程序的传输层将收到的网络结果进行逆向处理,得到实际的协议数据;
(11) Thrift客户端的协议层将数据按照协议格式进行解封装,然后得到具体的函数执行结果,并将其交付给调用函数;
上述过程如图4.1所示:
图4.1、调用过程中Thrift的各类协同工作过程
上图4.1的客户端协议类和服务端协议类都是指具体实现了TProtocol接口的协议类,在实际开发过程中二者必须一样,否则便不能进行通信;同样,客户端传输类和服务端传输类是指TTransport的子类,二者也需保持一致;
在上述开发thrift客户端和服务器端程序时需要用到三个类:传输类(TTransport)、协议接口(TProtocol)和处理类(Processor),其中TTransport是抽象类,在实际开发过程中可根据具体清空选择不同的实现类;TProtocol是个协议接口,每种不同的协议都必须实现此接口才能被thrift所调用。例如TProtocol类的实现类就有TBinaryProtocol等;在Thrift生成代码的内部,还需要将待传输的内容封装成消息类TMessage。处理类(Processor)主要在开发Thrift服务器端程序的时候使用。
来源:CSDN
作者:qq_40628566
链接:https://blog.csdn.net/qq_40628566/article/details/82884644