类体系结构图
protocol下层是transport层,负责数据的传输;上层是processor层,负责具体的业务逻辑函数路由和调用;protocol层介于transport层和processor层之间,负责数据的编解码,所以可以使用protocol相关的对象进行具体的序列化。主要包括如下几个类:
TBinaryProtocol:二进制格式序列化
TJSONProtocol:json格式序列化
TCompactProtocol:紧凑格式的序列化,类似Variable-length quantity编码
TDebugProtocol:文本格式的序列化,方便debug
TDenseProtocol:密集格式序列化,相比TCompactProtocol,减少了部分元数据的传输;目前仍处于实验阶段
每个protocol类都有一个工厂类和其对应。类体系结构图如下:
TProtocol、TProtocolDefaults、TVirtualProtocol
对于每种基本的类型,TProtocol类都有相应的read和write方法和其对应;对于非基本类型,如map、list、struct等,也有对应的readxxxBegin和writexxxEnd方法和其对应;除了数据类型,消息也需要传输,所以也定义了消息的读写方法。TProtocol类中包含两类方法,各类数据读写的纯虚函数和供用户调用的具体函数。
比如纯虚函数:
virtual uint32_t writeBool_virt(const bool value) = 0;
比如供用户调用的具体函数:
uint32_t writeBool(const bool value) {
T_VIRTUAL_CALL();
return writeBool_virt(value);
}
我们看到writeBool中会调用writeBool_virt。
TProtocolDefaults类继承自TProtocol类,这个类提供了TProtocol类中非纯虚函数的默认实现,默认实现除了抛异常什么也没做,如下:
uint32_t writeBool(const bool value) {
(void) value;
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support writing (yet).");
}
下面分析一下为什么会存在TProtocolDefaults这样一个类,以及为什么会做这样的默认实现。
首先来看一下TVirtualProtocol中是什么样子的,TVirtualProtocol是一个模板类,它包含两个参数,第一个是具体的protocol子类,表示数据传输的真正协议,第二个是protocol的默认实现,默认是TProtocolDefaults,主要是供TVirtualProtocol来继承,如下:
template <class Protocol_, class Super_=TProtocolDefaults>
class TVirtualProtocol : public Super_ {
}
TVirtualProtocol中对TProtocol中的纯虚函数做了默认实现,默认实现中调用了具体协议的非虚实现,如下:
virtual uint32_t writeBool_virt(const bool value) {
return static_cast<Protocol_*>(this)->writeBool(value);
}
综上,我们看到,基类TProtocol中的writeBool调用了它对应的纯虚函数writeBool_virt,子类TVirtualProtocol中的writeBool_virt又调用了具体子类中的writeBool,那么如果具体子类,比如TCompactProtocol,没有重写writeBool,必然会调用父类TProtocol中的writeBool,这样就造成了循环调用。所以为了避免无穷递归调用,引入了TProtocolDefaults,TVirtualProtocol继承自它,它里面的writeBool实现避免了递归调用,如果具体子类没有实现writeBool,则会抛出TProtocolException异常。
下面来分析一下,为什么会多出TVirtualProtocol这一层,直接让具体子类继承TProtocol不就得了。这里引用 这里 的一段分析:
为什么需要对这部分的类继承架构进行分析了?上面不是有很清楚的类继承关系图了吗?但是Facebook在实现时并不是简单的这样继承下来就可以了,Facebook为了后期协议的可扩展性和允许其他组织、团队或个人实现自己的数据传输(主要是数据格式的封装)协议,里面多加了一层继承关系,就是类图中的TVirtualProtocol类,从类的名称可以看出这是一个虚的协议。怎样理解这个虚的协议了?通过阅读代码我觉得可以这样理解:因为它定义为一个模板类,这个模板类有两个参数,一个用于数据传输的真正协议,一个是用来继承的,它本身没有对协议具体内容做实现,所以说它是一个虚的协议类。