13、JSON和ProtoBuf序列化

序列化/反序列化框架

  • JSON :可读性强,字符串,性能差。对于性能要求不是太高的服务器程序,用JSON较好

  • ProtoBuf:二进制框架,性能强。netty和微信都在用此框架

详解粘包和拆包(传输中会有半包问题)

netty发送数据和读取数据的场所是ByteBuf缓冲区

存在的问题:

  • 读到多个客户端的ByteBuf的输入,但是“粘”在了一起
  • 读到部分ByteBuf的内容,并且有乱码

第一种就是粘包,第二种就是半包,粘包和半包可以统称为传输中的半包问题

JSON传输的编码器和解码器原理

JSON 格式仅仅是字符串的一种组织形式,所以,传输JSON 所用到的协议与传出普通文本所使用的协议没有什么不同
都是用常用的 Head-content协议来进行JSON的传输

解码原理:

13、JSON和ProtoBuf序列化_第1张图片

  • 用LengthFieldBasedFrameDecoder(Netty内置解码器),将Head-content接收,当length==content.size()的时候,
    将content部分的二进制内容交给channelPipeline的下一个节点StringDecoder处理器进行解码
  • StringDecoder(Netty内置解码器)将入站的二进制数据解码成JSON字符串,交给下个节点处理
  • JsonMsgDecoder(不是Netty内置的解码器,是自定义的),将JSON字符串转化成Java POJO对象。

编码原理:

13、JSON和ProtoBuf序列化_第2张图片

  • StringEncoder(Netty内置的编码器)将JSON字符串编码成二进制数组,交给LengthFieldPerpender编码器
  • LengthFieldPerpender(Netty内置的编码器)将字符串数组编码成 Head-content二进制数据包。

JSON小结:LengthFieldBasedFrameDecoder解码器和LengthFieldPerpender解码器常常配套使用

ProtoBuf协议通信

ProtoBuf是Google提出的一种数据交换的格式,独立于语言,独立于平台
适用于分布式场景下的数据通信和异构环境下的数据交换。

ProtoBuf协议与JSON的不同:

  • JSON的编码:Java POJO–>字符串–>二进制数组
    JSON的解码:二进制数组–>字符串–>Java POJO对象
  • ProtoBuf的编码:Java POJO–>二进制数组
    ProtoBuf的解码:二进制数组–>Java POJO

ProtoBuf的解码和编码比JSON都少了一次转换,而且ByteBuf会更小,会减少解码器等待Head-content 中content的次数和时间
ProtoBuf为了减少传输包的大小,Head-content中的Head部分为varint32类型,varint32为可变长度类型。
int 占4个字节, varint32 可占2个字节或4个字节

ProtoBuf的编码过程:

  • 提前定义好需要传输的Message数据结构
  • 编码成二进制码流进行传输或存储
  • 将二进制码流解码成预先定义的Message结构的POJO实例

ProtoBuf使用proto文件来预先定义消息格式,proto文件,简单的说,就是一个消息的协议文件,这个协议文件的后缀是.proto

        // [开始头部声明]
        //syntax为版本号,如果不设置,默认为proto2
        syntax = "proto3";//类似Java中的包
        package com.crazymakercircle.netty.protocol;// [结束头部声明]// [开始java选项配置]
        //java_package,首先声明是Java语言,package如果不声明,默认用头部的包路径
        option java_package = "com.crazymakercircle.netty.protocol";//此选项表示在编译生成Java POJO类时,如果该.proto定义的全部POJO消息类都作为内部类打包在一个外部类中
        //那么该字符串内容作为外部类的类名
        option java_outer_classname = "MsgProtos";// [结束java选项配置]// [开始消息定义]
        message Msg {
          uint32 id = 1;  //消息ID
          //String 为字符串类型 content为该类的属性(字段),2不是content的值
          //2是代表在反序列化生成Java POJO类的时候,该字段在类中的排序。
          string content = 2; //消息内容
        }// [结束消息定义]

.proto文件中消息的字段类型
13、JSON和ProtoBuf序列化_第3张图片
此表时 .proto文件的消息类型和Java字段的对应

.proto文件嵌套消息

message Outer {        // Level 0
          message MiddleA{     // Level 1
            message Inner {    // Level 2
              int64ival = 1;
              bool booly = 2;}}
          message MiddleB{     // Level 1
            message Inner {    // Level 2
              int32ival = 1;
              bool  booly = 2;}}}

你可能感兴趣的:(netty)