thrift调用流程分析

因为工做须要使用thrift,而且须要根据需求修改thrift源码,所以必须熟悉thrift执行的流程。如下是根据thrift源码阅读而得出流程分析。服务器

thrift协议栈概述

thrift是一个rpc框架,开发者能够经过thrift自带的接口定义语言(IDL)来自动生成客户端和服务端的rpc代码。
thrift协议栈以下图所示:多线程

thrift架构

在client和server的最顶层都是用户自定义的处理逻辑,也就是说用户只须要编写用户逻辑,就能够完成整套的rpc调用流程。用户逻辑的下一层是thrift自动生成的代码,这些代码主要用于结构化数据的解析、发送和接收,同时服务端的自动生成代码中还包含了rpc请求的转发(client的A调用转发到server A函数进行处理)。架构

从上面能够看出thrift的模块是分层设计的,在每个层次能够根据业务的实际须要选择合适的实现方式。并发

thrift主要分为如下几种层次模块:框架

  • 底层io模块,负责实际的数据传输,包括socket、文件或压缩数据流等。
  • transport层负责以字节流方式发送和接收消息,是底层io模块在thrift框架中的实现,每个底层io模块都会有一个对于TTransport来负责thrift的字节流(byte stream)数据在该io模块上的传输。例如,TSocket对应socket传输,TFileTransport对应文件传输。
  • TProtocol主要负责结构化数据组装成消息,或者从消息结构中读出结构化数据。TProtocol将一个有类型的数据转化为特定类型的数据。如int32会被TBinaryProtocol编码为一个4字节数据,或TBinaryProtocol从TTransport中取出4个字节数据解码为int32。
  • TServer负责接收client请求,并将请求转发到processor进行处理。TServer主要任务是高效地接受client的请求,特别是高并发请求的状况下快速完成请求。
  • processor负责对client的请求进行响应,包括rpc请求转发,调用参数解析和用户逻辑调用,返回值写回等处理步骤。processor是服务端从thrift框架转入用户逻辑的关键流程。processor同时也负责向消息结构中写入数据或读出数据。

TServer

thrift核心库提供了一个TServer抽象类。socket

TServer在thrift框架中的主要任务是接收client请求,并转发到某个processor上进行请求处理。针对不一样的访问规模,thrift提供了不一样TServer模型。thrift目前支持的server模型包括:函数

  • TSimpleServer:使用阻塞io的单线程服务器,主要用于调试。
  • TThreadedServer:使用阻塞io的多线程服务器,每个请求都在一个线程中处理,并发访问状况下会有不少线程同时运行。
  • TThreadPoolServer:使用阻塞io的多线程服务器,使用线程池管理处理线程。
  • TNonBlockingServer:使用非阻塞io的多线程服务器,使用少许线程既能够完成大并发量的请求响应,必须使用TFramedTransport。

TServer对象一般以下工做:高并发

  1. 使用TServerTransport得到一个TTransport。
  2. 使用TTransportFactory,可选地将原始传输转换为一个合适的应用传输。
  3. 调用TProtocolFactory,为TTransport建立一个输入和输出。
  4. 调用TProcessor对象的process方法。

TTransport

TTransport是与底层数据传输紧密相关的传输层。每一种支持的底层传输方式都存在一个与之对应的TTransport。在这一层,数据是按字节流处理的,即传输层看到的是一个又一个的字节,并把这些字节按顺序发送和接收。TTransport并不了解它所传输的数据是什么类型,实际上传输层也不关心数据是什么类型,只须要按照字节方式对数据进行发送和接收便可。数据类型的解析在TProtocol这一层完成。编码

TTransport具体的有如下几个类:spa

  • TSocket:使用阻塞的TCP socket进行数据传输,也是最多见的模式。
  • THttpTransport:采用http传输协议进行数据传输。
  • TFileTransport:文件(日志)传输类,容许client将文件传给server,容许server将收到的数据写到文件中。
  • TZlibTransport:与其余transport配合使用,压缩后对数据进行传输,或者将收到的数据解压。

TProtocol

TProtocol的主要任务是把TTransport中的字节流转换为数据流。在TProtocol这一层就会出现具备数据类型的数据,如整型、浮点数、字符串和结构体等。TProtocol中数据虽然有了数据类型,但TProtocol只会按照指定类型将数据读出和写入,而对于数据的真正用途,须要在thrift自动生成的server和client中处理。

thrift可让用户选择客户端与服务端之间传输通讯协议的类别,在传输协议上整体划分为文本和二进制传输协议,以节约带宽,提升传输效率,通常状况下使用二进制类型的传输协议为大多数。经常使用协议有如下几种:

  • TBinaryProtocl:二进制编码格式
  • TCompactProtocol:高效率的、密集的二进制编码格式
  • TJSONProtocol:使用JSON的数据编码协议进行数据传输
  • TSimpleJSONProtocol:提供JSON只写协议,生成的文件很容易经过脚本语言解析
  • TDebugProtocol:简单易懂的文本格式,以便于debug

TProcessor

TProcessor主要对TServer中一次请求的inputProtocol和outputProtocol进行操做,也就是从inputProtocol中读出client的请求数据,向outputProtocol写入用户逻辑的返回值。TProcessorprocess是一个很是关键的处理函数,由于client全部的rpc调用都会通过该函数处理并转发。

TProcessor对一次rpc调用的处理流程能够归纳为:

  1. TServer接收到rpc请求以后,调用TProcessorprocess进行处理。
  2. TProcessorprocess首先调用TTransport.readMessageBegin接口,读出rpc调用的名称和rpc调用类型。若是rpc调用类型是rpc call,则调用TProcessor.process_fn继续处理,对于未知的rpc调用类型,则抛出异常。
  3. TProcessor.process_fn根据rpc调用名称,到本身的processMap中查找对应的rpc处理函数。若是存在对应的rpc处理函数,则调用该处理函数继续进行请求响应。不存在则抛出异常。

而rpc处理函数是rpc请求的最终步骤,主要有如下三个过程:

  1. 调用rpc请求参数的解析类,从TProtocol中读入数据完成参数解析。无论rpc调用的参数有多少个,thrift都会将参数放到一个结构体中。thrift会检查读出参数的字段id和字段类型是否与要求的参数匹配。对于不符合要求的参数都会跳过。这样,rpc接口发生变化以后,旧的处理函数在不作修改的状况下,能够经过跳过不认识的参数,来继续提供服务。
  2. 参数解析完后,调用用户逻辑,完成真正的请求响应。
  3. 用户逻辑的返回值使用返回值打包类进行打包,写入TProtocol。

ThriftClient

ThriftClient跟TProcessor同样主要操做inputProtocol和outputProtocol,不一样的是thriftClient将rpc调用分为send和receive两个步骤:

  1. send步骤,将用户的调用参数做为一个总体的struct写入TProtocol,并发送到TServer。
  2. send结束后,thriftClient便当即进入receive状态等待TServer的响应。对于TServer的响应,使用返回值解析类进行返回值解析,完成rpc调用。
相关文章
相关标签/搜索