文档章节

Protobuf简介

 张永昌
发布于 2015/08/26 16:54
字数 900
阅读 31
收藏 0
点赞 0
评论 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
武汉
基于Go语言的protobuf 安装 以及简单测试用例

先去官网下载protobuf的源码 https://github.com/google/protobuf/releases 可以先下载本地,然后上传到虚拟机中 我选择的是Source code(tar.gz) 安装依赖包(如果缺少包,可能会报错) yum i...

故新 ⋅ 06/13 ⋅ 0

google的protobuf库

这篇文章将讲述如何使用google的protobuf库实现一个RPC service,就实现一个最简单的service吧:echo.文章对应的代码都可以在eventrpc中找到,写下这篇文章时的svn revision是138. 1) 定义协议首...

moki_oschina ⋅ 06/06 ⋅ 0

grpc| python 实战 grpc

date: 2018-5-15 22:12:32 title: grpc| python 实战 grpc description: 只要代码可以跑起来, 很多难题都会迎刃而解. so, keep coding and stay hungry. 之前用 swoole 写 server 时就接触过...

daydaygo ⋅ 05/16 ⋅ 0

用 Maven 实现一个 protobuf 的 Java 例子

原文出处:jihite 1. 介绍Protocol Buffers Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化,常用于RPC 系统(Remote Procedure Call Protocol System...

jihite ⋅ 05/14 ⋅ 0

在项目中使用Protobuf协议实现数据传输(二)

上篇已经简单的分析了什么是ProtoBuf协议的优缺点、简单的环境配置、项目中的简单使用和一些编写.Proto文件的注意点,下面我们更加深入一下ProtoBuf的语法及高级使用(非常感谢Carson_Ho大神...

大荣言午 ⋅ 05/31 ⋅ 0

hadoop2.6.4 安装和编译

hadoop集群搭建 tools: SecureCRT8.0 VMware12 RHEL 6.6 x64 网络规划: hadoop0 192.168.248.150 hadoop1 192.168.248.151 hadoop2 192.168.248.152 hadoop3 192.168.248.153 设置静态ip:......

lizer2016 ⋅ 2016/07/26 ⋅ 0

Protobuf序列化对象放到redis

安装Protobuf 下载包,3.0+; 解压包; make; make check; make install; 构建模板 指定3.0+版本 生成protof文件: 引入依赖: 如果使用json,引入依赖: 构建对象并序列化放到redis red...

春哥大魔王的博客 ⋅ 04/17 ⋅ 0

hadoop-2.6.4集群编译搭建-阿里云和腾讯云

腾讯云阿里云 hadoop集群编译搭建 环境准备 阿里云配置: 腾讯云配置: 创建用户 useradd hadoop passwd haddop jdk1.7安装: 下载:http://www.oracle.com/technetwork/java/javase/downloa...

lizer2016 ⋅ 2016/07/31 ⋅ 0

ProtoBuf Window 使用 Protoc.exe 生成文件路径问题

Window操作系统下 参考《Netty权威指南第二版》中对ProtoBuf的讲解部分,用Protoc.exe 生成java文件会报Missing input file 错误。 解决办法: cmd 这样写: > protoc ./SubscribeReq.proto ...

@林文龙 ⋅ 06/07 ⋅ 0

springboot整合gprc 传输对象

一,grpc简介: GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x,基于Netty 4.x +。GRPC与thrift、avro-rpc等其实在总体原理上并没有太大的区别,简而言之...

xiaomin0322 ⋅ 04/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysql in action / alter table

change character set ALTER SCHEMA `employees` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci ;ALTER TABLE `employees`.`t2` CHARACTER SET = utf8mb4 , COLLAT......

qwfys ⋅ 今天 ⋅ 0

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

MySQL

查看表相关命令 - 查看表结构    desc 表名- 查看生成表的SQL    show create table 表名- 查看索引    show index from  表名 使用索引和不使用索引 由于索引是专门用于加...

stars永恒 ⋅ 昨天 ⋅ 0

easyui学习笔记

EasyUI常用控件禁用方法 combobox $("#id").combobox({ disabled: true }); ----- $("#id").combobox({ disabled: false}); validatebox $("#id").attr("readonly", true); ----- $("#id").r......

miaojiangmin ⋅ 昨天 ⋅ 0

金山WPS发布了Linux WPS Office

导读 近日,金山WPS发布了Linux WPS Office中文社区版新版本,支持大部分主流Linux系统,功能更加完善,兼容性、稳定性大幅度提升。本次更新WPS将首次在Linux提供专业办公文件云存储服务,实...

问题终结者 ⋅ 昨天 ⋅ 0

springboot2输出metrics到influxdb

序 本文主要研究一下如何将springboot2的metrics输出到influxdb maven <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-bo......

go4it ⋅ 昨天 ⋅ 0

微信小程序 - 选择图片显示操作菜单

之前我分享过选择图片这个文章,但是我在实际开发测试使用中发现一个问题在使用 wx.chooseImage 选择照片显示出第一格是拍照,后面是相册里的图片。这种实现之前说过了,效果如下。 但是你从...

hello_hp ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部