Protobuf学习笔记

Protobuf学习笔记

Protocol buffers是什么?

首先了解一下Protocol Buffers(简称ProtoBuf)是什么?官网对它的定义如下:

Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler.

上述定义描述了Protocol Buffers的全部优点:语言无法,平台无关,可扩展,用于序列化结构化数据。在官方定义之外我认为protobuf一种通用结构化组织数据描述语言,拥有一整套的简单语法规则,内置的类型系统等等。因此在学习过程中,可以把它当作一门简单的语言来看待。Protocol Buffers定义了描述文件的结构,而描述文件结构的语法检查,类型检查则需要protoc来处理,这时protoc就是一个编译器,在编译过程中不但检查语法还负责生成指定格式的目标文件。
Protocol Buffers为以.proto文件生成的各种对象(不限语言)的提供一致的序列化手段,保证数据最终持久化后的格式一致。而需要序列化的数据,由用户根据.proto文件提供的类,创建相应的对象。

Protobuf的描述文件 proto

在使用Protobuf时,定义描述文件是最重要的事情。Protobuf描述文件格式如下:

/*** Created by IntelliJ IDEA.* User: huxing(xing.hu@360hqb.com)* Date: 12-5-22* Time: 下午2:22*/
package org.colorfuldays.ssm.domain.protobuf;option java_package = "org.colorfuldays.ssm.domain.protobuf";message User{optional int64 id = 1;optional string name = 2;optional string password = 3;
}message book{optional int64 id = 1;optional string name = 2;optional string isbn = 3;repeated User author = 4;optional int64 publish_date = 5;
}
  • proto文件结构
    从上面的代码可以看出,proto文件的结构非常简单。
    package java_package 定义生成的java类的package名称。
    message定义一种类型,类型以Java中的一个class,book是类名,在生成Java代码时,就是使用这个类名。
    接下来是该类型中包含的字段,字段包括 [限定符 类型 字段名称 = tag [default = 默认值]]
  • protobuf支持的类型
    protobuf支持的默认类型如下
    .proto TypeNotesC++ TypeJava Type
    double doubledouble
    float floatfloat
    int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32int
    int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64long
    uint32Uses variable-length encoding.uint32int1
    uint64Uses variable-length encoding.uint64long1
    sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32int
    sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64long
    fixed32Always four bytes. More efficient than uint32 if values are often greater than 228.uint32int1
    fixed64Always eight bytes. More efficient than uint64 if values are often greater than 256.uint64long1
    sfixed32Always four bytes.int32int
    sfixed64Always eight bytes.int64long
    bool boolboolean
    stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringString
    bytesMay contain any arbitrary sequence of bytes.stringByteString

除此之外,还支持枚举,自定义类型等。使用方式见上面代码示例。更详细的介绍见官方文档
protobuf的自定义类型,支持对象组合方式,在CPP中使用较少,在Java中广泛采用,但是目前我们需要序列化的对象是瘦模型,用不上这种特性。

  • protobuf的限定符
  • required 必填项,如果该项不设值,在序列化时会抛出RuntimeException,推荐不使用该字段,该字段一旦使用,无法更改。不利于以来的扩展
  • optional 不存在时使用默认值,默认值可自定义。系统默认值如下:int = 0,bool = false,string=”"
  • repeated 类似于Java中的List,在实际生成Java类时,也是生成一个List来表示
  • tag说明
    tag 的主要作用是用来标识每一个field,序列化时会使用tag,取值为数字。如上面的id = 1,其中的1,即为tag。
    在protobuf序列化encode时标识每一个field,0-15比16-少一个byte,优化时可以使用到。
  • default值
    proto文件中定义的默认值在处理版本兼容时非常有用,下面会做相关介绍。
  • guide style
    Protocol Buffers官方提供了一个Guide Style。其中介绍了一些定义proto的优秀实践。一句话总结就是名称时,message名称以驼峰方式定义,字段名则需要以如author_name方式定义。字段名在生成Java代码时,会自动转换为符合Java风格的命名方式。

如何在项目中组织proto文件,暂时能想到下面三种方式:
1、一个项目中所有的class都在一个*.proto中定义?
2、每个class作为单独的文件?
3、按模块划分.proto文件
目前还没有确认哪种方式更佳。

Protobuf 生成的对象及序列化

Protobuf 生成的Java对象是immutable的,生成后无法修改,生成的Java对象以Builder方式构建,在调用Builder时为field设值。

  • 序列化方法
    Java接口提供的序列化相关方法如下:
    byte[] toByteArray();: serializes the message and returns a byte array containing its raw bytes.
    static Person parseFrom(byte[] data);: parses a message from the given byte array.
    void writeTo(OutputStream output);: serializes the message and writes it to an OutputStream.
    static Person parseFrom(InputStream input);: reads and parses a message from an InputStream.

    在处理序列化及反序列化对象时,发现难于对序列化方法的抽象,因为上述几个方法都不是public的。因此在序列化对象时,需要针对每一个Java对象实现其特定的序列化类。

扩展问题

Protobuf提供了极佳的扩展性,在扩展时,必须满足下面的要求:

  • you must not change the tag numbers of any existing fields.
  • you must not add or delete any required fields.
  • you may delete optional or repeated fields.
  • you may add new optional or repeated fields but you must use fresh tag numbers (i.e. tag numbers that were never used in this protocol buffer, not even by deleted fields).

在扩展之后可以实现下面的世界通
旧的系统可以读新的数据,但是无法读取到新添加的内容
新的系统可以读旧的数据,读不到的新加元素使用默认值

 旧数据新数据
旧系统不变忽略新添加的字段
新系统不存在的字段取默认值,删除的字段取默认值,无变化
缺点:

Protobuf无疑是一个非常优秀的结构化数据序列化协议,现在我们来说一说在Java环境下,它的一些缺点:
1、不支持大数据集的处理,少于1M
2、不支持Date,Map这些Java内建的对象

更多详细信息请参照官方文件https://developers.google.com/protocol-buffers/docs


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353835.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tortoise SVN 版本控制常用操作知识

Tortoise SVN 版本控制常用操作知识 Posted on 2010-11-26 23:07 szh114 阅读(5897) 评论(0) 编辑 收藏 今天老大跑过来问我如何把SVN服务器上的当前版本回退到某一个版本上去,我没回答上来,很失败,所以现在整理一下Tortoise SVN的操作知识&…

如何导入任何JBoss BRMS示例项目

在过去几周内,JBoss BRMS演示的用户反复询问我以下内容时,会给您这些提示和技巧: “如何将与各种JBoss BRMS演示项目相关的项目导入到我自己的现有安装中?” 这意味着用户希望在产品的个人安装中有一个示例项目,而无…

2110: 扫雷

http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id2110 2110: 扫雷 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 88 Solved: 36[Submit][Status][Web Board]Description 扫雷游戏你一定玩过吧!现在给你若干个nm的地雷阵,请你计算出每个矩阵中每…

青椒苗

转载于:https://www.cnblogs.com/wainiwann/p/8793418.html

如何开始Java机器学习

什么是开始使用Java机器学习的最佳工具? 他们已经存在了一段时间,但如今看来,每个人都在谈论人工智能和机器学习。 对于科学家和研究人员而言,它已不再是秘密,几乎可以在任何新兴技术中实现。 在下面的文章中&#x…

ztree树

常规的ztree树 后台数据封装成list对象 public PageModel getTreeBuildingRegData(Map<String, String> params) {PageModel pageModelnew PageModel();String statusparams.get("status");String orgIdparams.get("org_id");List<OmsBuildingReg…

如何提高效率

如何提高效率 时间管理 April 28th, 2011 本文来自读者 桃雨 翻译投稿。 Aaron Swartz写过一篇很有名的文章&#xff0c;叫做《HOWTO: Be more productive》&#xff08;如何提高效率&#xff09;。这篇文章写的实在是太好了&#xff0c;我看了好多遍&#xff0c;很赞同作者的…

Andrew Ng - 深度学习工程师 - Part 2. 改善深层神经网络:超参数调试、正则化以及优化(Week 1. 机器学习的实用层面)...

第1周 机器学习的实用层面 1.1 训练/开发/测试 早期机器学习时代&#xff08;数据规模较小&#xff09;&#xff0c;如果不需要dev set&#xff0c;常见的划分有 70%/30% 的训练/测试 划分&#xff0c;如果需要验证集&#xff0c;常见的是 60%/20%/20%划分 在big data era&…

jms 如何测试_使用JMSTester对JMS层进行基准测试

jms 如何测试对于我去过的大多数客户端&#xff0c;使用ActiveMQ扩展JMS消息传递层是一个优先事项。 有多种方法可以实现这一目标&#xff0c;但毫无疑问&#xff0c;创建基准并分析实际硬件上的体系结构&#xff08;或者正如我的同事Gary Tully所说的“询问机器”&#xff09;…

为什么待办事项清单不管用

为什么待办事项清单不管用 时间管理 November 22nd, 2012 本文原文来自 Harvard Business Review&#xff0c;由 换装迷宫tayy 翻译。 停止制作你的待办事项清单吧。它们只会让你感觉失败和受挫。想想你正在管理的那些待办清单&#xff1a;有多少事项从年初起就已经在那儿了&…

charts 画饼图

统计某一天某类物体的百分比 新知识点&#xff1a;aggregate https://blog.csdn.net/congcong68/article/details/51619882 主要的 $group $match $sort $limit pipeline [{$group:{_id:$area,count:{$sum:1}}}, # count 是聚合之后新增的一个字段。{$sort:{count:1}}, # …

Apache Camel 2.18 –即将推出的功能的亮点

骆驼骑士正在忙于即将发布的Apache Camel 2.18版本。 当我们动态更新发行说明时 &#xff0c;这是一种快速查看即将发生的情况的方法。 我只是想在夏天在这里进行快速更新&#xff0c;到目前为止&#xff0c;我们已经完成了简短的重点介绍。 随着发行版的临近和文档的完善&…

实时多线程系统的日志实现

实时多线程系统的日志实现 2008-03-21 09:19 黄明/戴颖  软件世界 我要评论(0) 字号&#xff1a;T | T为了分析软件系统在测试和运行期产生的故障&#xff0c;目前大多数软件系统所广泛使用的一种方法就是日志记录。本文给出了利用循环缓冲区和单独的日志读写线程实现实时系统…

Java中获取当前函数名

Java中获取当前函数名 博客分类&#xff1a; Java JavathreadJDKIDEA 有时候我们需要在程序中获取当前运行的函数名&#xff0c;如何简单的做到这点呢&#xff1f;我们可以用getStackTrace轻松搞定。 一提到getStatckTrace多数人会联想到Thowable中的getStackTrace方法。的确&…

建站手册-网站主机:电子商务主机

ylbtech-建站手册-网站主机&#xff1a;电子商务主机1.返回顶部 1、http://www.w3school.com.cn/hosting/host_ecommerce.asp2、2.返回顶部1、如果您的公司正在销售某种产品或服务&#xff0c;那么电子商务也许是做生意的一种好办法。 Internet 商业 电子商务就是在 Internet 上…

ConcurrentLinkedQueue

ConcurrentLinkedQueue 因为ConcurrentLinkedQueue是线程序安全的并且是针对并发的 主类 Java代码 public class conn{ public static void main(String[] args) throws Exception{ Queue<String> queuenew ConcurrentLinkedQueue<String>(); …

【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

每天学习一点点 编程PDF电子书、视频教程免费下载&#xff1a;http://www.shitanlife.com/code一、反向代理&#xff1a;Web服务器的“经纪人” 1.1 反向代理初印象 反向代理&#xff08;Reverse Proxy&#xff09;方式是指以代理服务器来接受internet上的连接请求&#xff0c;…

STM32-RS485通信软硬件实现

OS&#xff1a;Windows 64 Development kit&#xff1a;MDK5.14 IDE&#xff1a;UV4 MCU&#xff1a;STM32F103C8T6/VET6 AD&#xff1a;Altium Designer 18.0.12 1、RS485简介  RS-485又名TIA-485-A, ANSI/TIA/EIA-485或TIA/EIA-485。RS485是一个定义平衡数字多点系统中的驱动…

Java 枚举7常见种用法

DK1.5引入了新的类型——枚举。在 Java 中它虽然算个“小”功能&#xff0c;却给我的开发带来了“大”方便。 用法一&#xff1a;常量 在JDK1.5 之前&#xff0c;我们定义常量都是&#xff1a; publicstaticfianl....。现在好了&#xff0c;有了枚举&#xff0c;可以把相关的常…

深度学习训练数据打标签过程

深度学习训练数据打标签过程 为了获取大量的图片训练数据&#xff0c;在采集数据的过程中常用视频的方式采集数据&#xff0c;但对于深度学习&#xff0c;训练的过程需要很多的有有标签的数据&#xff0c;这篇文章主要是解决视频文件转换成图片文件&#xff0c;并加标签&#x…