dubbo的编码和序列化

为什么要序列化和反序列化

RPC过程必然要序列化和反序列化。

RPC是远程过程调用,A调用B,要经过网络,就会有数据传输,那就得在A端把请求参数序列化之后通过网络送到B端,B端进行反序列化。然后指向B服务,返回结果首先要在B端做序列化,之后通过网络送到A端,A端进行反序列化。这是一个完整的请求过程。分别产生2次序列化和反序列化动作。

为什么要编码和反编码

A调用B时,会传递信息,其中有一些公共的信息(包括序列化方式,序列化id,报文内容长度,这是请求报文还是返回报文等等)每次都要传递,非常规范,并且与业务无关。那我们就希望把它封装起来,在框架层面统一约定和处理。

这个过程类似于ISO7层协议模型在网络层的处理方式,分层处理。关于Dubbo报文的详细解释在Dubbo官方文档-实现细节中有详细说明,请查阅。

image

我觉得光看Dubbo官方文档的说明,还没法有非常强烈的感觉。这边贴了张它的图,并且拦截了一个实际的案例报文案例来分析一下。

image

上面这张图就是Request请求报文的截图,不太好看。仔细分析,会发现与Dubbo官方文档的说明是能对上的。

Magic High:11011010(0xda)

Magic Low:10111011(0xbb)

后面8位分别代表4个信息,1.请求报文,2.需要返回,3.非事件类型,4.用fastjson做序列化

64位Request ID都是0

报文长度:10111110 = 190

后面就是版本号,服务名字等等,每个信息之间都是以换行符来分隔0x0a。下面再把这个二进制对应的16进制图也贴一下。

image

序列化的结构设计

image

序列化模块的类结构比较简单,Serialization是接口,其他各个都是序列化的具体实现类。

@SPI("hessian2")// hessian2是默认实现
public interface Serialization {

    // 获取序列化写入器
    @Adaptive
    ObjectOutput serialize(URL url, OutputStream output) throws IOException;
        
    // 获取反序列化读取器
    @Adaptive
    ObjectInput deserialize(URL url, InputStream input) throws IOException;
}

发现Serialization的各个子类并非实际的做序列化和反序列化动作,而是分别委托给了ObjectOutputObjectInput来完成。

下面看看ObjectOutputObjectInput的结构,结构不复杂。内部各自实现各自的序列化和反序列化动作。

image

总结下序列化模块,这个模块从结构上非常简单,基本没有对其他模块的依赖,因为它在最底层。其次,它对外只需要暴露 Serialization接口就能对外发布服务。

编码和解码

先看下Codec2的类图

image

从类图本身看,结构并不复杂,只是DubboCodec的继承链路会比较长。那是因为它有自定义报文。所有的编码和解码都需要自己实现。内部实现的代码结构也比较复杂,说实话,那部分代码写的并不优雅。在优雅代码汇总篇中有详细分析。

DubboCodec这个类的继承和实现关系,有些奇怪,都已经做了一些列的继承关系,其父类也实现了Codec2接口。它自己还去实现了Codec2。我也没有猜到作者的用意是啥,或者只是忘记删除了。

ThriftThriftNative都是自己实现编码和解码操作。那开发者也可以实现自己的编码和解码操作,并且配置上去。

看看Codec2的接口

public interface Codec2 {
        // 编码行为
    @Adaptive({Constants.CODEC_KEY})
    void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException;
        // 解码行为
    @Adaptive({Constants.CODEC_KEY})
    Object decode(Channel channel, ChannelBuffer buffer) throws IOException;
}

Codec2接口就2个行为,分别是编码和解码,很容易理解。但子类对这两个行为的实现却是很复杂,这边不展开讲解了,主要怕我自己写吐了。有兴趣的朋友可以自己追踪下代码,也没必要逐行折腾,那部分代码写的比较乱,会看的比较头疼。

看到Codec2的一个子类CodecAdapter,从字面意思可以理解它是适配器模式。追踪下源码会发现它是用来适配Codec(上一代)的编码和解码的。这边只是引导下,不展开说了。

编码和解码其中一个步骤就是序列化和反序列化,编码模块依赖序列化模块,看下依赖的衔接点。下面贴了CodecSupport的代码,因为这个类的代码比较长,所以省去了大堆的代码,只是示意下。有兴趣的朋友自己追踪下源码。

public class CodecSupport {
        // ----------------------省略一堆代码-------------------------
    public static Serialization getSerializationById(Byte id) {
        // ----------------------省略一堆代码-------------------------
    }

    public static Serialization getSerialization(URL url) {
                // ----------------------省略一堆代码-------------------------
    }

    public static Serialization getSerialization(URL url, Byte id) throws IOException {
        // ----------------------省略一堆代码-------------------------
    }
   // ----------------------省略一堆代码-------------------------
}

通过CodecSupport的三个静态方法可以方便获取到Serialization的具体实例对象。然后做序列化和反序列化操作。

看到这边的参数(Byte id),可能会有些疑惑。这个时候要去看下Dubbo官方文档-实现细节。会看到

Serialization ID (5 bit)

Identifies serialization type: the value for fastjson is 6.

说明请求和返回报文都会把序列化方式来回传递。

总结

编码和序列化模块相对比较独立,主要是作为工具模块而存在。可扩展性也很强,开发者可以自由做横向扩展。不过有啥必要呢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352