Thrift之Protocol源码分析

简介: 之前写过两篇关于 Thrift 的相关文章。Thrift源码剖析Thrift异步IO服务器源码分析也算是对Thrift比较熟悉,不过对 Thrift 里面的 Protocol 部分还是黑盒使用。


之前写过两篇关于 Thrift 的相关文章。

也算是对Thrift比较熟悉,不过对 Thrift 里面的 Protocol 部分还是黑盒使用。 虽然大概能猜到具体实现方式,但是还是忍不住花了一点点时间把具体代码实现翻出来看看。 主要是为了满足一下好奇心。

简单搞了一个Thrift的描述文件Insight.thrift作为例子。

struct Person {
    1: string name,
    2: i32 age,
    3: optional string address,
}

service Insight {
    Person Hello(1: Person person),
    Person Hi(1: Person p1, 2: Person p2),
}

然后通过 毕竟Thrift其实就是干RPC的活,所以看源码就按着RPC远程调用的顺序来看就行。

从Hello函数调用开始,InsightClient::Hello 可以看出, 在每次RPC调用的时候,会先将函数名通过writeMessageBegin(“Hello”, ::apache::thrift::protocol::T_CALL, cseqid) 先发送过去。 这个过程的序列化协议很简单,直接就是传输的函数名字符串。 然后再发送参数。 发送参数的时候,会将所有参数作为一个 struct 发送 Insight_Hello_pargs

所以协议的序列化过程主要都是体现在 struct 的序列化上面。 比如像Hi函数的参数序列化过程:

uint32_t Insight_Hi_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const {
  uint32_t xfer = 0;
  xfer += oprot->writeStructBegin("Insight_Hi_pargs");

  xfer += oprot->writeFieldBegin("p1", ::apache::thrift::protocol::T_STRUCT, 1);
  xfer += (*(this->p1)).write(oprot);
  xfer += oprot->writeFieldEnd();

  xfer += oprot->writeFieldBegin("p2", ::apache::thrift::protocol::T_STRUCT, 2);
  xfer += (*(this->p2)).write(oprot);
  xfer += oprot->writeFieldEnd();

  xfer += oprot->writeFieldStop();
  xfer += oprot->writeStructEnd();
  return xfer;
}

整个对象的序列化过程主要是依赖了接口 TProtocol 的函数。

对于实现 TProtocol 接口的序列化实现主要是以下三种(在thrift-0.9.0/lib/cpp/src/thrift/protocol里):

  • TBinaryProtocol
  • TCompactProtocol
  • TJSONProtocol

要了解协议序列化过程主要看一下 TBinaryProtocol 和 TCompactProtocol 就够了。

主要是如下几个关键点:

  • 其实 writeStructStruct 和 writeStructEnd 啥屁事也不用做。
  • 其实 writeFieldBegin 只有后两个参数有用,第二个参数是类型,第三个参数是ID, 因为光靠这两者就可以在反序列化(读取解析)的时候知道是哪个成员了。
  • struct write 的过程其实是个递归的过程,也就是在write函数中, 会递归的调用结构体本身每个成员的write函数。
  • TCompactProtocol 和 TBinaryProtocol 的区别主要是, TCompactProtocol 对整数类型使用了 ZigZag 压缩算法,比如 i32 类型的整数本来是4个字节, 可以压缩成 1~5 字节不等。而 i64类型的整数本来是8个字节。可以压缩成 1~10 字节不等。

http://yanyiwu.com/work/2015/04/05/thrift-protocol-insight.html

目录
相关文章
|
Java Go Apache
gRPC vs Thrift
远程过程调用(Remote Procedure Call,RPC)服务于分布式架构,本文从分布式构架面临的问题,期望的结果,引出两种比较受关注的RPC框架,并从框架的出身、实现原理、特性、性能等方面做了对比分析,从而给出两者之间的选择建议。
11039 0
|
分布式计算 数据挖掘 程序员
Thrift简介—续
Thrift简介—续
Thrift简介—续
|
存储 自然语言处理 负载均衡
|
存储 监控 网络协议
netty系列之:在netty中使用proxy protocol
我们知道proxy protocol是haproxy提出的一个代理协议,通过这个协议,所有实现这个协议的proxy或者LBS,都可以附带真实客户端的IP地址和端口号,这使得proxy protocol在实际应用中非常有用。 这么优秀的协议,没有理由netty不支持。本文将会谈一下netty中对proxy protoco代理协议的支持。
|
JSON 网络协议 Java
thrift 原理浅析
thrift 原理浅析
275 0
thrift 原理浅析
|
存储 Java 程序员
Java学习笔记——dubbo服务之底层通讯协议Protocol
我们先来找到通讯协议的入口点吧。通过Protocol接口查找通讯协议入口点,我们根据接口的export方法搜索发现入口了,在ServiceConfig的doExportUrlsFor1Protocol方法,如下图: 然后我们进入 protocol.
1711 0
|
缓存
spark2.1.0之源码分析——RPC客户端TransportClient详解
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/82143001 提示:阅读本文前最好先阅读: 《Spark2.
1642 0
|
网络协议
Thrift源码解析--transport
这一层主要是用于实现网络通信,现在都是基于Tcp/Ip,而Tcp/Ip协议栈由socket来实现,换句话说就是现在网络通信服务底层大都是通过socket实现的,在thrift源码中,就是将socket包装成各种transport来使用。
747 0
|
JSON Java Apache
thrift概述
Apache Thrift 是FaceBook实现的一种跨平台的远程服务调用(RPC)的框架。它采用接口描述语言(IDL)定义并创建服务,传输数据采用二进制格式,相对于XML和Json等常用数据传输方式体积更小。
921 0