一、protocal buffer 是什么?

一种序列化机制。

什么是序列化?

一种转化为可存储和传输对象的过程。

序列化的方式有很多,那么proto有什么特殊的呢?

它的英文介绍里提到了neutral这个词,中立,无关的。

language-neutral 跨语言:它可以应用于多种开发语言之间数据交互。

platform-neutral 跨平台:它可以运行于多种系统平台

可扩展

序列化过程性能优越,速度快

序列化后为二进制数据,相对的占用空间更小(存储成本及传输成本)及一定程度的保障数据的安全性。

提供支持多语言的自动化代码生成工具,开发易用性

二、下面以一个简单地示例开始:

proto3 文件:.proto

syntax = "proto3";

message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}

第一行声明当前使用的proto3版本协议语法(proto编译器默认使用proto2版本协议语法),声明必须为文件的第一行,此前不能有任何内容,包括注释。

消息使用“message”关键字定义,内部以“字段类型 字段名称 = 字段序号;”形式定义所要包含额属性。

1、序号:

每一个字段被赋予一个唯一的序号,起始为1不可重复。通常考虑到向后兼容的因素,不建议修改已定义的字段序号。

需要注意的是,序号大小会影响序列化编码的空间占用,例如:

序号范围[1,15]:proto使用1个字节存储字段的序号及类型,适宜定义常用字段。

序号范围 [16,2047]:proto使用2个字节存储字段的序号及类型。

...

序号可用域[1,229 - 1],其中[19000,19999]为proto保留序号范围(编译使用),不可使用。另外,开发方可以约定保留序号,以供扩展或其它特殊使用。

2、字段约束

singular:更直观的可以用optional来释义,可选字段,0个或1个,proto3中未默认约束。

repeated:列表集合字段类型,可以包含 >=0 个字段元素。

三、数据类型

proto3编码类型对应不同开发语言数据类型:

.proto Type 说明 Java Type
double   double
float   float
int32

使用可变长编码。

对于负数编码效率较低(可以使用sint32类型存储)

int
int64

使用可变长编码。

对于负数编码效率较低(可以使用sint64类型存储)

long
uint32 使用可变长编码。 int[1]
uint64 使用可变长编码。 long[1]
sint32 使用可变长编码,存储有符号整数。尤其对负数编码效率更高。 int
sint64

使用可变长编码,存储有符号整数。尤其对负数编码效率更高。

long
fixed32 四字节空间占用。存储值>228时,存储效率高于uint32。 int[1]
fixed64

八字节空间占用。存储值>256时,存储效率高于uint64。

long[1]
sfixed32 四字节空间占用 int
sfixed64 八字节空间占用 long
bool   boolean
string UTF-8编码或者7位ASCII文本,长度不可超过232 String
bytes 可以存储任何二进制数据,长度不可超过232 ByteString

四、默认值

singular 类型字段在进行编解码时,如果没有进行赋值则赋予默认值。不同类型使用默认值如下:

类型 默认值
string 空字符串
bytes 空byte数组
bool false
数值类型 0
enums 定义的枚举第一个元素(默认必须为0)
定义的message类型 不赋值
repeated * 空列表

proto3关于默认值的操作,在我们实际的使用中不免会造成一些困扰,我们需要去区分未知结果默认值结果两者之间的区别。例如,我们定义了bool类型字段updated(是否已更新),默认的false所表示未更新,则会将未知是否已更新覆盖。

对于此,通常处理的方式是引入包装类型wrapper,使用如下:

import "google/protobuf/wrappers.proto";

wappers.proto文件定义如下:

// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Wrappers for primitive (non-message) types. These types are useful
// for embedding primitives in the `google.protobuf.Any` type and for places
// where we need to distinguish between the absence of a primitive
// typed field and its default value.
//
// These wrappers have no meaningful use within repeated fields as they lack
// the ability to detect presence on individual elements.
// These wrappers have no meaningful use within a map or a oneof since
// individual entries of a map or fields of a oneof can already detect presence. syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option cc_enable_arenas = true;
option go_package = "github.com/golang/protobuf/ptypes/wrappers";
option java_package = "com.google.protobuf";
option java_outer_classname = "WrappersProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB"; // Wrapper message for `double`.
//
// The JSON representation for `DoubleValue` is JSON number.
message DoubleValue {
// The double value.
double value = 1;
} // Wrapper message for `float`.
//
// The JSON representation for `FloatValue` is JSON number.
message FloatValue {
// The float value.
float value = 1;
} // Wrapper message for `int64`.
//
// The JSON representation for `Int64Value` is JSON string.
message Int64Value {
// The int64 value.
int64 value = 1;
} // Wrapper message for `uint64`.
//
// The JSON representation for `UInt64Value` is JSON string.
message UInt64Value {
// The uint64 value.
uint64 value = 1;
} // Wrapper message for `int32`.
//
// The JSON representation for `Int32Value` is JSON number.
message Int32Value {
// The int32 value.
int32 value = 1;
} // Wrapper message for `uint32`.
//
// The JSON representation for `UInt32Value` is JSON number.
message UInt32Value {
// The uint32 value.
uint32 value = 1;
} // Wrapper message for `bool`.
//
// The JSON representation for `BoolValue` is JSON `true` and `false`.
message BoolValue {
// The bool value.
bool value = 1;
} // Wrapper message for `string`.
//
// The JSON representation for `StringValue` is JSON string.
message StringValue {
// The string value.
string value = 1;
} // Wrapper message for `bytes`.
//
// The JSON representation for `BytesValue` is JSON string.
message BytesValue {
// The bytes value.
bytes value = 1;
}

五、枚举

enum 枚举对象 {

UNKOWN = 0; //默认值机制使用(首先必须有一个枚举值为0的枚举实例,其次兼容proto2中使用第一个变量为默认值的机制)

枚举实例 = 枚举值;

... ...

}

六、定义更新

1、不可修改已定义的字段序号。

2、可以删除已定义的字段,但是其序号不可在被使用。

3、int32, uint32, int64, uint64及bool是相互兼容的,只不过转换过程会产生值域变更

4、sint32 和 sint64 是相互兼容的。

5、byte3存储值为有效UTF-8编码内容时与string相互兼容。

七、未知字段

未能对应解析的字段会存储于未知字段中。此机制在proto3中最初抛弃,v3.5版本重新引入。

八、Map 类型

定义如下:

map<key_type, value_type> map_field = N。

key_type:任何整形或者string类型。

value_type:可以为除了Map类型外的任何类型。

proto3 协议指引的更多相关文章

  1. Golang使用proto3协议导致零值字段不显示

    Golang使用proto3协议导致零值字段不显示 问题描述 proto协议生成的结构体如果使用直接转成json会导致零值字段不显示,这样的json是有毛病的,可以使用如下方法解决 示例Demo pa ...

  2. Golang语言下使用Protocol Buffer教程

    代码仓库地址 一.介绍 Protobuf是Google旗下的一款平台无关,语言无关,可扩展的序列化结构数据格式.所以很适合用做数据存储和作为不同应用,不同语言之间相互通信的数据交换格式,只要实现相同的 ...

  3. .NET Core使用gRPC打造服务间通信基础设施

    一.什么是RPC rpc(远程过程调用)是一个古老而新颖的名词,他几乎与http协议同时或更早诞生,也是互联网数据传输过程中非常重要的传输机制. 利用这种传输机制,不同进程(或服务)间像调用本地进程中 ...

  4. HTTP和RPC是现代微服务架构,HTTP和RPC是现代微服务架构

    .NET Core使用gRPC打造服务间通信基础设施   一.什么是RPC rpc(远程过程调用)是一个古老而新颖的名词,他几乎与http协议同时或更早诞生,也是互联网数据传输过程中非常重要的传输机制 ...

  5. 使用gRPC打造服务间通信基础设施

    一.什么是RPC rpc(远程过程调用)是一个古老而新颖的名词,他几乎与http协议同时或更早诞生,也是互联网数据传输过程中非常重要的传输机制. 利用这种传输机制,不同进程(或服务)间像调用本地进程中 ...

  6. protobuf3的学习笔记

    学习protobuf的过程中踩了不少的坑,这篇博文算是一个小结吧! 环境: windows VisualStudio Google.Protobuf.Tools. Google.Protobuf. 其 ...

  7. GO gRPC教程-环境安装(一)

    前言 gRPC 是一个高性能.开源和通用的 RPC 框架,面向移动和 HTTP/2 设计,带来诸如双向流.流控.头部压缩.单 TCP 连接上的多复用请求等特.这些特性使得其在移动设备上表现更好,更省电 ...

  8. gRPC-微服务间通信实践

    微服务间通信常见的两种方式 由于微服务架构慢慢被更多人使用后,迎面而来的问题是如何做好微服务间通信的方案.我们先分析下目前最常用的两种服务间通信方案. gRPC(rpc远程调用) 场景:A服务主动发起 ...

  9. grpc系列- protobuf详解

    Protocol Buffers 是一种与语言.平台无关,可扩展的序列化结构化数据的方法,常用于通信协议,数据存储等等.相较于 JSON.XML,它更小.更快.更简单,因此也更受开发人员的青眯. 基本 ...

随机推荐

  1. thinkphp如何实现伪静态

    去掉 URL 中的 index.php ThinkPHP 作为 PHP 框架,是单一入口的,那么其原始的 URL 便不是那么友好.但 ThinkPHP 提供了各种机制来定制需要的 URL 格式,配合 ...

  2. 基于go-cqhttp实现QQ机器人

    本篇文章记录一下自己在编写QQ机器人的时候所遇到的一些问题和核心功能的实现. QQ机器人RabbitBot采用python编写,由于是个人学习使用,故目前不会开源完整代码,只会放出核心代码供学习参考. ...

  3. 浅析Linux用户空间中的Mmap

    一.MMap基础概念 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系.实现这样的映射关系后,进程就可以采 ...

  4. Mybatis参数预编译

    Mybatis参数预编译 一.数据库预编译介绍 1.数据库SQL语句编译特性: 数据库接受到sql语句之后,需要词法和语义解析,优化sql语句,制定执行计划.这需要花费一些时间.但是很多情况,我们的一 ...

  5. Python基础(if语句、运算符)

    if语句的简单用法 每条if 语句的核心都是一个值为True 或False 的表达式 (简称条件测试),python根据条件测试的值来判断是否执行if语句后面的代码块,如果为true,执行:为fals ...

  6. 2021最新WordPress安装教程(一):Centos7安装Apache

    一转眼2020年已经过去了,看网络上很多WordPress的安装教程都比较旧,有些写的不太详细,WordPress是站长最喜欢的一款建站系统,数据统计到2020年为止,WordPress在所有网站的市 ...

  7. 洛谷P2865

    感觉此题可作为严格次短路的模板,因此来写一写 Description 给定 \(n\) 个点,\(r\) 条双向道路,求从 \(1\) 号点到 \(n\) 号点的严格次短路 Solution 维护两个 ...

  8. MVC架构 项目实践

    MVC MVC架构程序的工作流程 springmvc 中dao层和service层的区别 项目实践 项目目录 项目实现流程 JSP登录页面View层 LoginServletjavaControlle ...

  9. 阿里云MQ

    阿里云众多中间件服务中有一款非常强大的中间见服务,在企业互联网架构中起到不可替代的作用,相比较开源的RabbitMQ,阿里的消息队列MQ承受的住阿里内部1000+核心应用的使用,每天转几千条消息,稳定 ...

  10. 我用了半年的时间,把python学到了能出书的程度

    Python难学吗?不难,我边做项目边学,过了半年就通过了出版社编辑的面试,接到了一本Python选题,并成功出版. 有同学会说,你有编程基础外带项目实践机会,所以学得快.这话不假,我之前的基础确实加 ...