简要介绍和总结protobuf的一些关键点,从我之前做的ppt里摘录而成,希望能节省protobuf初学者的入门时间。这是一个简单的Demo。

Protobuf 简介

Protobuf全称Google Protocol Buffers

  • http://code.google.com/p/protobuf
  • 结构化数据存储格式(xml, json)
  • 用于通信协议、数据存储等
  • 高效的序列化和反序列化
  • 语言无关、平台无关、扩展性好
  • 官方支持C++, Java, Python三种语言

.proto文件

定义和使用

消息定义文件user_def.proto

package user;
message UserInfo {
required int64 id = ;
optional string name = ;
repeated bytes nick_name = ;
}

编译.proto,生成解析器代码

protoc --cpp_out . user.proto  // user_def.pb.h user_def.pb.cc
protoc --java_out . user.proto // user/UserInfo.java

字段ID

optional string name = 2;

  • 唯一性
  • 序列化后,1~15占一个字节,16~2047占两个字节

字段类型

编写建议

  1. 常用消息字段(尤其是repeated字段)的ID尽量分配在1~15之间。
  2. 尽可能多的(全部)使用optional字段。
  3. 命名方式
    • .proto文件名用underscore_speparated_names。
    • 消息名用CamelCaseNames。
    • 字段名用underscore_separated_names。

兼容性建议

  1. 不能修改字段的ID。
  2. 不能增删任何required字段。
  3. https://developers.google.com/protocol-buffers/docs/proto#updating

序列化后的protobuf消息

  • 一序列的键值对,键是消息字段的ID。
  • 已知消息字段(.proto文件定义)按其ID顺序排列。
  • 未知消息字段:
    • c++和java: 排在已知字段之后且顺序不定。
    • python: 不保留未知字段。
  • 不包含未赋值的optional消息字段。
  • 使用little-endian字节序存储。

反射

反射是protobuf的一个重要特性,涉及到的类主要有:

根据名称创建消息

以下是一个根据消息名(包含package name)创建protobuf消息的C++函数,需要注意的是返回的消息必须在用完后delete掉。

Message* createMessage(const string &typeName) {
Message *message = NULL;
// 查找message的descriptor
const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(typeName);
if (descriptor) {
// 创建default message(prototype)
const Message *prototype = MessageFactory::generated_factory()->GetPrototype(descriptor);
if (NULL != prototype) {
// 创建一个可修改的message
message = prototype->New();
}
}
return message;
}

修改消息

根据消息的字段名称修改其值。以上面的user.UserInfo为例,下面将一个新的UserInfo消息的其id字段设为100。

int main() {
// 使用上面的函数创建一个新的UserInfo message
Message *msg = createMessage("user.UserInfo");
if (NULL == msg) {
// 创建失败,可能是消息名错误,也可能是编译后message解析器
// 没有链接到主程序中。
return -;
} // 获取message的descriptor
const Descriptor* descriptor = msg->GetDescriptor();
// 获取message的反射接口,可用于获取和修改字段的值
const Reflection* reflection = msg->GetReflection(); // 根据字段名查找message的字段descriptor
const FieldDescriptor* idField = descriptor->FindFieldByName("id");
// 将id设置为100
if (NULL != idField) {
reflection->SetInt64(msg, idField, );
} // ... 其他操作 // 最后删除message
delete msg; return ;
}

从字符串或流中读取消息

createMessage创建一个空的消息后,最常见的使用场景是使用Message的ParseFromString或ParseFromIstream方法从字符串或流中读取一个序列化后的message。

  Message *msg = createMessage("user.UserInfo");
if (NULL != msg) {
if (!msg->ParseFromString("... serialized message string ... ")) {
// 解析失败
...
}
}

Protobuf优势

  1. 扩展性好

    • 前后兼容
    • 引入(import)已定义的消息
    • 嵌套消息
  2. 高效 https://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking
    • 适合处理大量小数据(单个Message不超过1M)

Protobuf劣势

  1. 没有内置的Set, Map等容器类型。
  2. 不适合处理单个Message超过1M的情景,详见Large Data Sets

进一步阅读

阅读资料

Google Protocol Buffers介绍的更多相关文章

  1. Google Protocol Buffers 入门

    Google Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或 RPC 数据交换格式.可用于通讯协议.数据存储等领域的 ...

  2. C# 使用Google Protocol Buffers

    Google Protocol Buffers 使用3.0版本 下载protoc.exe 下载链接 https://github.com/protocolbuffers/protobuf/releas ...

  3. Protocol Buffers介绍及例子

    Protocol Buffers介绍及例子 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或数据交换格式.可用于通讯协 ...

  4. Google Protocol Buffers 快速入门(带生成C#源码的方法)

    Google Protocol Buffers是google出品的一个协议生成工具,特点就是跨平台,效率高,速度快,对我们自己的程序定义和使用私有协议很有帮助. Protocol Buffers入门: ...

  5. 开源点评:Protocol Buffers介绍

    今天来介绍一下“Protocol Buffers”(下面简称protobuf)这个玩意儿.本来俺在构思“生产者/消费者模式 ”系列的下一个帖子:关于生产者和消费者之间的传输数据格式.因为里面扯到了pr ...

  6. 【神经网络与深度学习】Google Protocol Buffer介绍

    简介 什么是 Google Protocol Buffer? 假如您在网上搜索,应该会得到类似这样的文字介绍: Google Protocol Buffer( 简称 Protobuf) 是 Googl ...

  7. Protocol buffers 介绍

    Protocol buffers和mxl一样在序列化数据结构时很灵活.高效和智能,但是它的优势在于定义文件更小,读取速度更快,使用更加简单.目前protocol buffers支持C++.java和p ...

  8. Protocol Buffers介绍

    基本概念 Protocol Buffers(以下简称PB)是一种独立于语言.独立于开发平台.可扩展的序列化数据结构框架,它常常被用在通信.数据序列化保存等方面. PB是一种敏捷.高效.自动化的用于对数 ...

  9. Google Protocol Buffers简介

    什么是 protocol buffers ? Protocol buffers 是一种灵活.高效的序列化结构数据的自动机制--想想XML,但是它更小,更快,更简单.你只需要把你需要怎样结构化你的数据定 ...

随机推荐

  1. SSM实战——秒杀系统之DAO层实体定义、接口设计、mybatis映射文件编写、整合Spring与Mybatis

    一:DAO实体编码 1:首先,在src目录下,新建org.myseckill.entity包,用于存放实体类: 2:实体类设计 根据前面创建的数据库表以及映射关系,创建实体类. 表一:秒杀商品表 对应 ...

  2. 【超精简JS模版库/前端模板库】原理简析 和 XSS防范

    使用jsp.php.asp或者后来的struts等等的朋友,不一定知道什么是模版,但一定很清楚这样的开发方式: <div class="m-carousel"> < ...

  3. JS:指定FPS帧频,requestAnimationFrame播放动画

    Flash制作动画,最基础的概念就是帧,但在Flash中,帧频的控制比较简单,只需要编译前指定一下目标帧频就可以了. 实际运行时,不需要我们关心定时器的问题,flash player会定时触发Ente ...

  4. java json与map互相转换(二)

      java json与map互相转换(二) CreationTime--2018年7月16日15点09分 Author:Marydon 1.准备工作 所需jar包: commons-beanutil ...

  5. mysql日期相关的函数

    1.获取当前时间: /** 获得当前日期+时间(date + time)函数:now(), 常用 **/ select now() from dual; /** 获取当前时间戳,current_tim ...

  6. 在QTableView中某列中添加Button的导致滚动条滚动的时候消失的问题

    之前在项目上需要在表格中加入Button是按照以下两个文章的做法: http://www.cnblogs.com/li-peng/p/3961843.html http://www.cnblogs.c ...

  7. 解决FatalThrowableError in EloquentUserProvider.php line 126: Class '\App\User'问题

    解决方法:http://stackoverflow.com/questions/28516454/laravel-5-user-model-not-found 总结:是因为我把app下的User移动到 ...

  8. 【转载】Mysql主从复制、和MySQL集群(主主复制)

    转载:https://www.cnblogs.com/phpstudy2015-6/p/6485819.html 请同时参考和结合这篇文件进行处理:https://blog.csdn.net/envo ...

  9. HanLP自定义词典注意事项

    对于词典,直接加载文本会很慢,所以HanLP对于文本文件做了一些预处理,生成了后缀名为.txt.bin的二进制文件. 这些二进制文件相当于缓存,避免了每次加载去读取多个文件. 通过这种txt和bin结 ...

  10. Ubuntu中root用户和user用户的相互切换[转载自93度的饼干]

    Ubuntu中root用户和user用户的相互切换 Ubuntu是最近很流行的一款Linux系统,因为Ubuntu默认是不启动root用户,现在介绍如何进入root的方法. (1)从user用户切换到 ...