• 结构化数据序列化机制--Protocol Buffers


    一、什么是pb协议?

    ProtoBuff是一种将结构化数据进行序列化和反序列化的方法。它的作用类似XML,它的优势主要体现在序列化后的数据小以及数据解析速度快。

    适用于对数据序列化后体积以及速度要求严格的场景,如在即时通信领域,移动端与服务器的交互比桌面端与服务器的交互更适合使用pb协议。

    二、pb与其他序列化机制对比

    同为序列化机制,pb相比于更加常见的用户数据交互的XML 、json各自有啥特点呢?

    1、json: 是一种轻量级的数据交换格式。使用键值对的方式对数据进行封装。使用简单,可读性较高,但不能表达复杂数据类型。一般的web项目中,最流行的主要还是json。因为浏览器对于json数据支持非常好,有很多内建的函数支持。 

    2、xml: 使用闭合标签对数据进行封装。在webservice中应用最为广泛,但是相比于json,它的数据更加冗余,因为需要成对的闭合标签。json使用了键值对的方式,不仅压缩了一定的数据空间,同时也具有可读性。 

    3、protobuf:是后起之秀,是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码,编码和解码双方必须有共同的proto文件。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。

    因此:
    在一个需要大量的数据传输的场景中,如果数据量很大,那么选择protobuf可以明显的减少数据量,减少网络IO,从而减少网络传输所消耗的时间。

    ---------------------
    以上参考:https://blog.csdn.net/u014043213/article/details/80336805

    如果已经决定使用pb,那么pb该怎么用呢?

    三、怎么使用pb?

    序列化基本步骤:

    定义proto文件 --> 编译proto文件 --> 导入编译后文件 --> 对消息中各个字段复制 -->序列化(即, 调用SeriotoString()得到二进制字符串)

    反序列化基本步骤:

    获取与序列化过程一致的proto文件 --> 

    下面以python语言下的序列化过程为例介绍:

    1、按照pb格式要求编写proto文件;

    一个简单的message格式:

    Message 消息名{
        字段规则 字段类型 字段名 = 分配标识号;
    }
    字段规则:required(必须设置) 、 optional(可以有0或1个) 、repeated(可以有0或多个)
    字段类型:可以是标准类型、枚举类型、自定义message类型
    分配标识名:1、2、3……

    2、使用pb编译器对proto文件进行编译:

    protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/你的.proto文件名 
    需要指定源目录(应用程序源码目录——如果不提供这个目录,默认就是当前目录),目标目录(你的应用程序编译后生成的代码的目录;通常用$SRC_DIR),
    还有.proto文件的目录路径.此时对应的.py文件就会生成在指定的目标目录中.因为我们case的编写框架为python,我们想生成Python的类,所以用–python_out选项,也有类似的选项支持其它语言,例如生成C++的类,用–cpp_out选项

    3、在项目中导入pb编译生成的类文件:

    4、创建类对象,并为对象的对各个字段进行赋值

    5、调用SerializeToString()方法进行序列化。

    --------------------- 
    参考:

    https://developers.google.cn/protocol-buffers/docs/overview

    https://www.sohu.com/a/168549441_216613

    https://www.cnblogs.com/tohxyblog/p/8974763.html

    https://www.jianshu.com/p/2265f56805fa

    四、使用pb中的坑

    1、pb在进行编码和解码时必须使用相同的.proto文件,之前一次工作中,仅仅更新了编码端的协议文件,服务器上文件未更新,总是出错,又是重新编译,又是反复看在编码端编译出来的类文件 ,折腾了好久,最后才意识到是两边的文件不一致,导致无法正常解析。其实这也体现了pb文件在使用过程中的一个缺点。普通序列化方式,只要在服务器端打出日志,传输的字段有没有错误就很显而易见,但是由于pb序列化的数据都是二进制格式的,日志打印出来都是乱码,如果真的遇到业务错误,也不太直接看出来是传输字段有错误还是其他哪里的错误。不过,一般情况下严格按照步骤使用,出错倒是不多。

    2、repeated修饰符修饰的字段在使用时候的有一个注意点。在工作中,遇到过一个情况是,message中某个字段的字段规则是repeated,字段类型是自定义message类型。在这种场景下,对字段进行赋值的时候,需要先对自定义类型message的字段调用add方法,初始化新实例;然后对新实例中的每个元素进行赋值。例如:

    message格式--

    字段赋值过程--

    Repeated修饰字段赋值注意:

    对基本message类型,直接赋值;

    对自定义message类型,调用add方法初始化新实例,再对实例中每个元素赋值

    对于基本数据类型,使用append()追加元素,如果是列表用extend()<这个未经历实践>
  • 相关阅读:
    Reactive(1) 从响应式编程到"好莱坞"
    [动图演示]Redis 持久化 RDB/AOF 详解与实践
    补习系列(22)-全面解读 Spring Profile 的用法
    Android手机打造你的Python&Java开发工具!
    人工神经网络模型种类
    最小二乘拟合
    LDA主体模型
    Logistic Regression求解classification问题
    batch gradient descent(批量梯度下降) 和 stochastic gradient descent(随机梯度下降)
    SVM实验
  • 原文地址:https://www.cnblogs.com/Jing-Wang/p/10958672.html
Copyright © 2020-2023  润新知