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