文档章节

Protobuf简介

 张永昌
发布于 2015/08/26 16:54
字数 900
阅读 74
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

Protobuf 简介

Protobuf全称Google Protocol Buffers

  • 结构化数据存储格式(xml, json)

  • 用于通信协议、数据存储等

  • 高效的序列化和反序列化

  • 语言无关、平台无关、扩展性好

  • 官方支持C++, Java, Python三种语言

.proto文件

定义和使用

消息定义文件user_def.proto

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

编译.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占两个字节

字段类型

  • string vs. bytes

    .proto类型 c++类型 java类型 说明
    string std::string String 必须是UTF-8或ASCII文本
    bytes std::string ByteString 任意的字节序列

编写建议

  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 -1;
    }

    // 获取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, 100);
    }

    // ... 其他操作

    // 最后删除message
    delete msg;

    return 0;
}

从字符串或流中读取消息

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

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

Protobuf优势

  1. 扩展性好

    • 前后兼容

    • 引入(import)已定义的消息

    • 嵌套消息

  2. 高效

    • 适合处理大量小数据(单个Message不超过1M)

Protobuf劣势

  1. 没有内置的Set, Map等容器类型。

  2. 不适合处理单个Message超过1M的情景,详见Large Data Sets

进一步阅读

阅读资料


粉丝 0
博文 1
码字总数 900
作品 0
武汉
私信 提问
加载中
请先登录后再评论。
开源数据访问组件--Smark.Data

Smark.Data是基于Ado.net实现的数据访问组件,提供基于强类型的查询表达式进行灵活的数据查询,统计,修改和删除等操作;采用基于条件驱动的操作模式,使数据操作更简单轻松;内部通过标准SQL...

泥水佬
2013/03/12
2.6K
0
跨平台开源通讯组件elastic communication

    elastic communication是基于c#开发支持.net和mono的通讯组件(简称EC),EC的主要目的简化mono和.net下的通讯开发难度,通过EC可以非常快速地开发基于mono和.net的通讯交互应用。E...

泥水佬
2015/12/01
656
0
HBase之HMaster工作原理

HMaster 监控所有的RegionServer,一般运行在namenode 架构图 从图中可以看出,主要有External Interfaces、Executor Services、Zookeeper System Trackers、File System Interfaces、Chore...

selfless
2016/04/24
2.3K
1
kubernetes+docker监控之简介

kubernetes+docker监控 Docker的监控原则:根据docker官方声明,一个容器不建议跑多个进程,所以不建议在容器中使用agent进行监控(zabbix等),agent应该运行在宿主机,通过cgroup或是docke...

perofu
2016/07/19
6.4K
10
YAML简介与使用实例

一、YAML介绍 YAML:是YAML Ain't a Markup Language(YAML不是一种置标语言)的递归缩写,早先YAML的意思其实是:Yet Another Markup Language(另外一种置标语言),但为了强调这种语言以数...

孟飞阳
2016/07/12
1.2K
3

没有更多内容

加载失败,请刷新页面

加载更多

数据库高频面试点,事务/乐观锁/悲观锁/CAS/MySQL存储引擎

事务的ACID特性是什么? 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用; 一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读...

osc_45536bvu
53分钟前
16
0
大数据BI软件助力企业数字化转型

当下,「新基建」势头正盛,随着“新基建”成为热议话题,数字化也随之成为企业面临的新机遇和新挑战。新基建的核心就是数据,数据是数字经济和企业数字化转型的生产要素和发展动力。 再看看...

osc_0boqdoe2
55分钟前
0
0
凯旋创投来志刚:基因治疗新时代,大戏刚刚开始

  2017 年,全球第一个基因治疗方法 CAR-T 细胞药物 Kymriah 获得 FDA 上市批准,从此掀起了基因治疗的热潮。随着相关技术和政策的不断成熟,基因治疗市场也随之扩大。根据德勤发布的《引领...

osc_k3vwonkw
56分钟前
10
0
LightningChart.NET使用两个BarSeries创建简单的2D图表

本教程介绍了如何使用两个BarSeries创建简单的2D图表。 BarSeries将数据值表示为矩形条,并且可以用于以非常清晰的方式可视化数据之间的差异和方差。 在本教程中,BarSeries用于表示两年期间...

roffey
57分钟前
0
0
Mybatis trim 标签的 2 个妙用!

云栖号资讯:【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! mybatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼...

osc_x03qsedc
57分钟前
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部