Protobuf

作者: 臻甄 | 来源:发表于2020-03-24 16:11 被阅读0次

    github:https://github.com/protocolbuffers/protobuf
    官方指南:https://developers.google.com/protocol-buffers/docs/overview

    中文指南:

    Overview (是什么)

    • Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准。
    • 含有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。
    • 用途:Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化。适合通讯、数据存储等。
      (1)Google用于 RPC 系统和持续数据存储系统。
      (2)可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
    • 目前提供了 C++、Java、Python 三种语言的 API。

    Install

    github库 下载源码并编译。Ubuntu安装比较方便。

    wget https://github.com/google/protobuf/releases/download/v2.4.1/protobuf-2.4.1.tar.gz
    tar -xzf protobuf-2.4.1.tar.gz 
    cd protobuf-2.4.1 
    ./configure
    make 
    make check # 这一步会报错,忽略即可,也可以跳过这一步
    make install
    

    安装完成后会在 /usr/local/bin 目录下生成一个可执行文件 protoc

    ls /usr/local/bin/protoc
    protoc --version  # 检查是否安装成功
    

    在Ubuntu下一般会报错,protoc: error while loading shared libraries: libprotoc.so.8: cannot open shared,原因是 protobuf 的默认安装路径是/usr/local/lib,而/usr/local/lib 不在Ubuntu体系默认的 LD_LIBRARY_PATH里,所以就找不到该lib,解决方案:添加路径即可。

    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    

    QuickStart

    参考

    Step 1. demo简介

    • 该程序(Protobuf & C++)由两部分组成。第一部分被称为 Writer,第二部分叫做 Reader。
    • Writer 负责将一些结构化的数据写入一个磁盘文件;
    • Reader 则负责从该磁盘文件中读取结构化数据并打印到屏幕上。

    Step 2. 定义.proto文件

    • 结构化数据,被称为Message,类似 java 或者 C 语言的数据定义
    package lm;  // package名字
    message helloworld   // 消息名称,该消息含有3个成员
    { 
       required int32     id = 1;  // ID 
       required string    str = 2;  // str 
       optional int32     opt = 3;  //optional field, 可选成员,即消息中可以不包含该成员
    }
    

    Proto文件的命名规则packageName.MessageName.proto

    Step 3. 编译.proto文件

    // SRC_DIR:放置.proto的目录
    // DST_DIR:输出.cc和.h文件的目录
    protoc -I=$SRC_DIR --cpp_out=$DST_DIR
    
    • 将生成两个文件
      lm.helloworld.pb.h : 定义了 C++ 类的头文件
      lm.helloworld.pb.cc : C++ 类的实现文件
    • 在生成的头文件中,定义了一个 C++ 类 helloworld,后面的 Writer 和 Reader 将使用这个类来对消息进行操作。诸如对消息的成员进行赋值,将消息序列化等等都有相应的方法。

    Step 4. 编写Writer 和 Reader

    • 为什么需要protobuf,数据的Read和Write,按理说其实有很多方法,但Read的码农,必须清楚了解Write的码农所用的格式和细节,比如123可以按照int存储也可以按照string存储
    • 使用protobuf的好处:
      (1)需要处理的结构化数据由.proto文件描述,Writer只需要include proto生成的.h文件就可以使用固定格式的类了。
      (2)protobuf集成了一系列全面鲁棒的方法来保证数据可以序列化和反序列化,可以放心的把数据存储交给protobuf
    • Writer代码
    #include "lm.helloworld.pb.h"
    int main(void) { 
      lm::helloworld msg1; 
      msg1.set_id(101);   // 设置 id 的值
      msg1.set_str(“hello”); 
         
      // Write the new address book back to disk. 
      fstream output("./log", ios::out | ios::trunc | ios::binary); 
    
      // SerializeToOstream 将对象序列化后写入一个 fstream 流
      if (!msg1.SerializeToOstream(&output)) { 
          cerr << "Failed to write msg." << endl; 
          return -1; 
      }         
      return 0; 
    }
    
    • Reader代码
    #include "lm.helloworld.pb.h" 
    void ListMsg(const lm::helloworld & msg) { 
      cout << msg.id() << endl; 
      cout << msg.str() << endl; 
     } 
      
     int main(int argc, char* argv[]) { 
      // 声明类 helloworld 的对象 msg1
      lm::helloworld msg1; 
      { 
        fstream input("./log", ios::in | ios::binary); 
        // 利用 ParseFromIstream 从一个 fstream 流中读取信息并反序列化
        if (!msg1.ParseFromIstream(&input)) {
          cerr << "Failed to parse address book." << endl; 
          return -1; 
        } 
      } 
      // ListMsg 中采用 get 方法读取消息的内部信息
      ListMsg(msg1); 
    }
    
    • 运行reader和writer结果如下:
    >writer 
    >reader 
    101 
    Hello
    
    • 把磁盘读写改为网络socket就可以扩展到RPC类的程序编写。
    • 存储和交换正是 Protobuf 最有效的应用领域。

    竞品对比

    • 竞品:XML,JSON,Thrift

    • protobuf的优点:简单,快

    • 项目 thrift-protobuf-compare
      比较了这些类似的技术,图 1 显示了该项目的一项测试结果,Total Time.

      total time
    • Total Time 指一个对象操作的整个时间,包括创建对象,将对象序列化为内存中的字节序列,然后再反序列化的整个过程。从测试结果可以看到 Protobuf 的成绩很好,感兴趣的读者可以自行到网站

    • Protobuf 优点:
      (1)Protobuf 有如 XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。修改简单。
      (2)即“向后”兼容性好:人们不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。方便升级和迁移代码。
      (3)Protobuf 语义更清晰,无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。
      (4)Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例。

    • Protobuf 缺点:
      (1)相比较 XML,Protobuf功能简单,无法用来表示复杂的概念。
      (2)XML 已经成为多种行业标准的编写工具,Protobuf 只是 Google 公司内部使用的工具,在通用性上还差很多。
      (3)由于文本并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。另外,由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上 Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容。


    推荐阅读:Protobuf更多高级应用和细节

    相关文章

      网友评论

          本文标题:Protobuf

          本文链接:https://www.haomeiwen.com/subject/ymijyhtx.html