Thrift系列 | Thrift框架源码分析

本文深入解析Thrift框架,从Thrift的理解、类概述到Protocol和Transport层的源码分析。Protocol层负责序列化和反序列化,包括TBinaryProtocol、TCompactProtocol等。Transport层涉及TSocket、TFramedTransport等,封装底层网络通信并提供缓冲。文章通过具体类的介绍和功能解释,展示了Thrift如何处理RPC的通信流程。
摘要由CSDN通过智能技术生成

1. Thrift框架理解

对于Thrift框架的理解,我们使用官方提供的框架图来讲解一下

  • client/server

    对于client来说,该层是比较简单的client的业务逻辑代码,而对于server来说,有提供的几种模式的server。

  • Thrift的Protocol层

    对于RPC来说需要能正确的传输调用的信息已经返回的结果,那么protocol层则主要负责序列化和反序列化,该层主要有以下几种,对于Binary来说,那么使用的是Binary的方式来进行序列化,那么会涉及到一定的协议格式,对于JSON来说,使用的则是以JSON的方式序列化。

  • Thrift的Transport层

    由于RPC是一种特殊的网络编程,那么需要封装一层传输层来支持底层的网络通信,而Transport则负责这层。Transport层不仅仅用来支持底层的网络通信,它可能还会对Protocol层的数据进一步分装。比如针对Framed类型来说,该层还会多4个字节的字段用来存储Protocol层的字节串长度。

那么针对采用TCP/IP作为更底层的通信协议的话,整个通信过程如下图所示

2. Thrift类概述

该图引用自CSDN_Thrift源码解析(一)主要类概述。该图解析的thrift源码是基于Java语言的1.0.0版本,虽然本系列接下去是基于C++在那进行讲解的,但是也具有一定的参考性。

根据上图大概可以分为以下几个类

  • TTransport:客户端传输层相关的类;
  • TServerTransport:服务端传输层相关的类;
  • TProtocol:序列化、反序列化相关的类;
  • TServer:服务器的IO事件流模型相关的类;
  • TProcessor:函数,接口调用相关的类;

下面主要针对TTransport和Tprotocol层的代码进行阐述。

3. Protocol层的源码

上面提到Protocol层主要是负责序列化的,Thrift的序列化协议主要包含以下几种,

  • TBinaryProtocol
  • TCompactProtocol
  • TJSONProtocol

以上这些协议都继承自TProtocol这个抽象类,那么我们先来看一下TProtocol这个类大致的内容,比较详细的可以直接去看c++源代码,该类中主要是一些读写函数的抽象,write主要负责序列化,read主要负责反序列化。

class TProtocol {
public:
  virtual ~TProtocol();

  /**
   * Writing functions.
   */

  virtual uint32_t writeMessageBegin_virt(const std::string& name,
                                          const TMessageType messageType,
                                          const int32_t seqid) = 0;

  virtual uint32_t writeMessageEnd_virt() = 0;

  virtual uint32_t writeStructBegin_virt(const char* name) = 0;

  virtual uint32_t writeStructEnd_virt() = 0;

  virtual uint32_t writeFieldBegin_virt(const char* name,
                                        const TType fieldType,
                                        const int16_t fieldId) = 0;

  virtual uint32_t writeFieldEnd_virt() = 0;

  virtual uint32_t writeFieldStop_virt() = 0;
	
    ......
        
  virtual uint32_t writeBool_virt(const bool value) = 0;

  virtual uint32_t writeByte_virt(const int8_t byte) = 0;

  virtual uint32_t writeI16_virt(const int16_t i16) = 0;

  virtual uint32_t writeI32_virt(const int32_t i32) = 0;

  virtual uint32_t writeI64_virt(const int64_t i64) = 0;

  virtual uint32_t writeDouble_virt(const double dub) = 0;

  virtual uint32_t writeString_virt(const std::string& str) = 0;

  virtual uint32_t writeBinary_virt(const std::string& str) = 0;
  
  /**
   * Reading functions
   */

  virtual uint32_t readMessageBegin_virt(std::string& name,
                                         TMessageType& messageType,
                                         int32_t& seqid) = 0;

  virtual uint32_t readMessageEnd_virt() = 0;

  virtual uint32_t readStructBegin_virt(std::string& name) = 0;

  virtual uint32_t readStructEnd_virt() = 0;

  virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) = 0;

	......
}        

下面我们重点看一下TBinaryProtocol的具体实现,这边就挑几个主要的进行阐述。

template <class Transport_, class ByteOrder_>
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeMessageBegin(const std::string& name,
                                                                     const TMessageType 																		 messageType,
                                                                     const int32_t seqid) {
  if (this->strict_write_) {
    int32_t version = (VERSION_1) | ((int32_t)messageType);
    uint32_t wsize = 0;
    wsize += writeI32(version);
    wsize += writeString(name);
    wsize += writeI32(seqid);
    return wsize;
  } else {
    uint32_t wsize = 0;
    wsize += writeString(name);
    wsize += writeByte((int8_t)messageType);
    wsize += writeI32(seqid);
    return wsize;
  }
}

template <class Transport_, class ByteOrder_>
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeFieldStop() {
  return writeByte((int8_t)T_STOP);
}

template <class Transport_, class ByteOrder_>
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeI32(const int32_t i32) {
  int32_t net = (int32_t)ByteOrder_::toWire32(i32);
  this->trans_->write((uint8_t*)&net, 4);
  return 4;
}

template <class Transport_, class ByteOrder_>
template <typename StrType>
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeString(const StrType& str) {
  if (str.size() > static_cast<size_t>((std::numeric_limits<int32_t>::max)()))
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  uint32_t size = static_cast<uint32_t>(str.size());
  uint32_t result = writeI32((int32_t)size);
  if (size > 0) {
    this->trans_->write((uint8_t*)str.data(), size);
  }
  return result + size;
}

template <class Transport_, class ByteOrder_>
uint32_t TBinaryProtocolT<Transport_, ByteOrder_>::writeBinary(const std::string& str) {
  return TBinaryProtocolT<Transport_, ByteOrder_>::writeString(str);
}

writeMessageBegin:序列化message的开始部分,可以理解为message的头部,thrift中的message表示一次接口调用、接口调用结果或者异常。这个函数中主要是调用相应的write函数来序列和写入thrift的版本、message的name以及seqid等基本信息,比如针对一个函数调用而言,那么name字段就是函数的名字。

writeFieldStop:所有字段序列化完成之后,调用writeByte函数写入一个T_STOP标识符,表示结束。

writeI32:序列化int类型的数据,调用protocol层封装的transport类的实例来写入一个int类型。

writeString:序列化string类型的数据,写入字符串的内容和4字节的字符串大小。

writeBinary:在C++中,binary类型还是按照string类型来写入。

相关的read操作就是上述write操作的逆操作者,想要了解的可以直接去看源码。

Thrift源码解析是通过分析Thrift框架的源代码来了解其内部工作原理和实现细节的过程。在这个过程中,我们可以深入了解Thrift框架中各个模块的功能和相互关系,以及具体的实现方式。 引用中提到了一篇博客文章《Thrift源码解析--Transport传输层分析》,该博客对Thrift框架中Transport传输层的实现进行了详细解析。传输层是Thrift框架中负责网络传输和数据序列化的模块,它定义了一系列的传输协议,如TBinaryProtocol、TCompactProtocol等,并提供了相应的传输方式,如TTransport、TServerTransport等。在这篇博客中,作者对Transport传输层的各个子模块进行了介绍,并详细解释了它们的实现原理和使用方法。 引用中提到了另一篇博客文章《Thrift源码解析(一)主要类概述》,该博客主要介绍了Thrift框架中的一些主要类和它们的作用。这些类包括TProcessor、TProtocol、TServer等,它们是Thrift框架中的核心组件,负责处理数据的编码、解码、处理和传输。在这篇博客中,作者通过对这些类的分析,帮助读者了解Thrift框架的整体结构和工作原理。 引用中提到了一个名为thrift-enhancer的工具包,该工具包是对Thrift协议的增强支持。它提供了动态解析IDL并生成参数对象的能力,生成的参数对象可以自动转换为Thrift协议数据,并且支持Thrift与JSON、XML的双向转换。thrift-enhancer的出现为Thrift源码解析提供了更多的工具和扩展功能,帮助开发者更好地理解和使用Thrift框架。 综上所述,Thrift源码解析是通过分析Thrift框架的源代码来了解其内部工作原理和实现细节的过程。通过阅读相关的博客文章和使用辅助工具,可以更深入地了解Thrift框架的各个模块和主要类的功能和实现方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值