`
836811384
  • 浏览: 549059 次
文章分类
社区版块
存档分类
最新评论

Thrift之TProtocol类体系原理及源码详细解析之类继承架构分析

 
阅读更多

我的新浪微博:http://weibo.com/freshairbrucewoo

欢迎大家相互交流,共同提高技术。


这部分相关的类主要实现与协议相关的内容,这里说的协议是指对数据传输格式封装的协议,实现不同的协议来适合不同场景下的数据传输,因为在不同的场景下不同协议对于数据传输来说效率有很大的差别。下面是这个部分相关类的类关系图:


由以上类图可以发现所有的协议类都从TProtocol类直接或间接继承,每一个协议类都有一个对应的生产对象工厂(协议工厂)。TProtocol是一个抽象的类,不能直接使用的,它有一个直接子类默认实现了所有方法(空实现),如果我们需要定义自己的数据传输协议可以直接从这个类继承。

第一节类继承架构分析

为什么需要对这部分的类继承架构进行分析了?上面不是有很清楚的类继承关系图了吗?但是Facebook在实现时并不是简单的这样继承下来就可以了,Facebook为了后期协议的可扩展性和允许其他组织、团队或个人实现自己的数据传输(主要是数据格式的封装)协议,里面多加了一层继承关系,就是类图中的TVirtualProtocol类,从类的名称可以看出这是一个虚的协议。怎样理解这个虚的协议了?通过阅读代码我觉得可以这样理解:因为它定义为一个模板类,这个模板类有两个参数,一个用于数据传输的真正协议,一个是用来继承的,它本身没有对协议具体内容做实现,所以说它是一个虚的协议类。下面我们对这个类继承架构结合代码实现来具体分析。

1抽象类TProtocol和默认实现类TProtocolDefaults

抽象类对于每一种数据类型都提供了读写的开始和介绍的方法,这里读写方法应该是针对网络IO读写,不过真正实现网络读写还不是这里的方法,这里方法主要处理数据,例如对数据格式做调整。真正实现网络IO读写是下一章介绍的TTransport相关类实现的,那里还会对传输的方式做相应控制,例如是否压缩。

除了具体的数据类型有写入和读取的方法,消息也是需要通过网络传递,所以也定义了消息的传输读写方法。当然还定义了一些公用的功能,如跳过某一个结构不读、大小端数据格式调整、主机字节序和网络字节序的相互转换等。

1)首先定义纯虚函数:

virtualuint32_twriteMessageBegin_virt(conststd::string&name,

constTMessageTypemessageType,constint32_tseqid)=0;

virtualuint32_twriteMessageEnd_virt()=0;

virtualuint32_twriteStructBegin_virt(constchar*name)=0;

virtualuint32_twriteStructEnd_virt()=0;

2)然后定义调用相应纯虚函数的函数:

uint32_twriteMessageBegin(conststd::string&name,constTMessageTypemessageType,constint32_tseqid){

T_VIRTUAL_CALL();//打印调用日志函数

returnwriteMessageBegin_virt(name,messageType,seqid);

}

uint32_twriteMessageEnd(){

T_VIRTUAL_CALL();

returnwriteMessageEnd_virt();

}

uint32_twriteStructBegin(constchar*name){//写结构体开始

T_VIRTUAL_CALL();

returnwriteStructBegin_virt(name);

}

uint32_twriteStructEnd(){//写结构体结束

T_VIRTUAL_CALL();

returnwriteStructEnd_virt();

}

3)其他公共函数

uint32_tskip(TTypetype){

T_VIRTUAL_CALL();

returnskip_virt(type);//跳过数据类型

}

virtualuint32_tskip_virt(TTypetype){

return::apache::thrift::protocol::skip(*this,type);//调用此命名空间下全局函数实现

}

4)全局数据结构定义

enumTType{//Thrift协议支持的数据类型枚举定义

T_STOP=0,

T_VOID=1,

T_BOOL=2,

T_BYTE=3,

T_I08=3,

T_I16=6,

T_I32=8,

T_U64=9,

T_I64=10,

T_DOUBLE=4,

T_STRING=11,

T_UTF7=11,

T_STRUCT=12,

T_MAP=13,

T_SET=14,

T_LIST=15,

T_UTF8=16,

T_UTF16=17

};

enumTMessageType{//thrift支持的消息类型

T_CALL=1,

T_REPLY=2,

T_EXCEPTION=3,

T_ONEWAY=4//函数的异步调用方式

};

还定义了一个对应抽象工厂类,用于上产具体的协议对象,这就是设计模式中最常用的抽象工厂设计模式。上面代码只是简单列举了两个写入的函数,还有其他很多相关数据类型的写入和读取函数因为都相同格式定义就没有具体拿出来说明了。

至于默认实现类TProtocolDefaults主要重写了抽象类TProtocol的非虚拟化的方法,这些方法都抛出一个方法为实现(TProtocolException::NOT_IMPLEMENTED)的异常。这样做的主要目的为了下面要讲到的类TVirtualProtocol提供默认的继承基类,从而防止无限递归调用。下面分析TVirtualProtocol类时具体分析如果没有这个默认实现类怎样产生无限递归调用。

2虚协议类TVirtualProtocol

首先看看这个特殊的模板类是怎样定义的:

template<classProtocol_,classSuper_=TProtocolDefaults>

classTVirtualProtocol:publicSuper_{

……//省略具体内容

}

说它特殊我觉得主要是基于两个方面:

1)继承的类可以通过模板参数传递,也就是说你现在没有办法肯定它现在带地继承什么类,只是默认参数值是我们上面介绍的抽象类的默认实现类。

2)类里面的方法实现全部是采用把this指针转换为第一个模板参数的类型然后调用模板参数类型的相关方法。如下面的一个方法的定义:

virtualuint32_twriteMessageBegin_virt(conststd::string&name,

constTMessageTypemessageType,constint32_tseqid){

returnstatic_cast<Protocol_*>(this)->writeMessageBegin(name,messageType,seqid);

}//实现抽象类的writeMessageBegin_virt方法

由上面两个特点可以发现这个类只是提供一个空的架构壳,继承的类可以指定,当然也可以采用默认的,后面分析具体协议实现的时候可以发现大多数协议也确实是采用默认的继承类,且大多数继承这个虚协议的类都是传递第一个参数为自身,也就是调用自己定义的相应函数。如TBinaryProtocolT类的定义,如下:

template<classTransport_>

classTBinaryProtocolT:publicTVirtualProtocol<TBinaryProtocolT<Transport_>>{

…….

}

下面来分析如果不从定义的默认实现类继承,直接从抽象类继承怎样会产生无限递归调用。现在我们假设直接从抽象类继承,那么如果一个指向子类对象的父类(TProtocol)调用writeMessageBegin方法,因为这个方法不是虚拟函数(不会动态绑定)所以就会调用父类的writeMessageBegin方法,然后父类会直接调用它的纯虚函数writeMessageBegin_virt,这个函数就会动态绑定,就会执行子类的实现,在这里就是通过虚协议类TVirtualProtocol实现的,而这个函数又会调用之类的writeMessageBegin方法,如果子类没有实现这个方法,那么就又回到父类的这个方法了,从而产生无限递归调用。那么如果默认是从默认实现类TProtocolDefaults继承,那么就会执行它的writeMessageBegin方法,从而抛出一个异常,就不会产生无限递归调用。

3具体协议类或实现自己的协议类

这个就是类继承架构的最后一部分,也就是实现具体的数据传输协议。例如二进制协议类定义如下:

template<classTransport_>

classTBinaryProtocolT:publicTVirtualProtocol<TBinaryProtocolT<Transport_>>{……}

那么这个二进制协议类就不用实现那些虚拟方法了。那些具体的协议实现方式后面详细介绍。

现在对这部分的类继承架构已经分析完毕,后面开始介绍Thrift中实现的几个比较重要的协议。

分享到:
评论

相关推荐

    thrift源码

    thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码thrift源码...

    thrift包及其源码

    thrift0.9.1版本的jar包,还有源码,可供大家参考学习使用。

    thrift源码+DEMO+简单教程

    thrift源码+DEMO+简单教程

    Apache Thrift Java实战源码,包含了客户端和服务端源码

    Apache Thrift Java实战源码,包含了客户端和服务端源码,客户端和服务端是分开的,如果需要放到一个工程,直接把Client.java文件复制到服务端运行即可。

    windows下vs2010编译的thrift,包含lib和cpp源码

    windows下vs2010完美编译thrift,包含lib文件和src源码,thrift版本为thrift-0.11.0

    thrift 架构的Java的小例子 demo

    此文件为自己在Mac电脑上写的thrift的demo,使用maven 管理了小程序,并用thrift生成了源码,其中对thrift生成的源码,把override注销了,其他的没处理,如果感兴趣参考博客:...

    Thrift之C++初体验

    thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, ...

    libthrift-1.0.0.jar,thrift例子,thrift源码

    libthrift-1.0.0.jar,thrift例子,thrift源码 里面有你想要java版的thrift全部文件

    Apache Thrift 使用说明

    详细介绍了Apache Thrift在Ubuntu以及Windows下基于C++和Java语言的安装和运行。附有小例子,亲自测试通过。所述方法网上应该有教程,但大多零散不统一或者不完整,因此本人整理了一份,特来分享。

    Thrift架构介绍.docx

    Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前...

    thrift-0.9.2.tar.gz

    thrift,Apache Thrift 0.9.2 版本,解压后直接直接安装,可伸缩的跨语言服务开发框架,命令: 解压命令:tar -zxf thrift-0.9.2.tar.gz 安装命令:./configure --with-lua=no && make && make install 查看版本:...

    Thrift结构分析及增加取客户端IP功能实现

    分析Thrift的结构动机是为了实现服务端能取到客户端的IP,因此需要对它的结构、调用流程有些了解。另外,请注意本文针对的是TNonblockingServer,不包含TThreadPoolServer、TThreadedServer和TSimpleServer。  ...

    thrift 源码(一种可伸缩的跨语言服务的发展软件框架)

    thrift是一种可伸缩的跨语言服务的发展软件框架。它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C + +,C#,Java,Python和PHP和Ruby结合。thrift是facebook开发的,我们现在把它作为...

    thrift例子

    NULL 博文链接:https://andilyliao.iteye.com/blog/1931911

    使用wireshark抓取thrift协议接口调用

    使用wireshark抓取thrift协议接口调用

    编译的spark-hive_2.11-2.3.0和 spark-hive-thriftserver_2.11-2.3.0.jar

    spark-hive_2.11-2.3.0...spark-hive-thriftserver_2.11-2.3.0.jar log4j-2.15.0.jar slf4j-api-1.7.7.jar slf4j-log4j12-1.7.25.jar curator-client-2.4.0.jar curator-framework-2.4.0.jar curator-recipes-2.4.0.jar

    基于Scala的Spark Thrift Server设计源码

    本设计源码提供了一个基于Scala的Spark Thrift Server。项目包含12731个文件,主要使用Scala、Java、Python、Shell、JavaScript、CSS、HTML、Ruby和C编程语言。文件类型包括3539个Scala源代码文件、1559个Q文件、...

    一种基于Thrift的日志收集分析系统_周康.pdf

    一种基于Thrift的日志收集分析系统_周康.pdf

    thrift-0.9.3.exe

    Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨...

    thrift安装

    thrift 安装包。

Global site tag (gtag.js) - Google Analytics