proto3 協議指引

1、protocal buffer 是什麼?

一種序列化機制。java

什麼是序列化?

一種轉化爲可存儲和傳輸對象的過程。git

序列化的方式有不少,那麼proto有什麼特殊的呢?

它的英文介紹裏提到了neutral這個詞,中立,無關的。github

language-neutral 跨語言:它能夠應用於多種開發語言之間數據交互。golang

platform-neutral 跨平臺:它能夠運行於多種系統平臺數組

可擴展安全

序列化過程性能優越,速度快app

序列化後爲二進制數據,相對的佔用空間更小(存儲成本及傳輸成本)及必定程度的保障數據的安全性。ide

提供支持多語言的自動化代碼生成工具,開發易用性工具

2、下面以一個簡單地示例開始:

proto3 文件:.proto 性能

syntax = "proto3";

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

第一行聲明當前使用的proto3版本協議語法(proto編譯器默認使用proto2版本協議語法),聲明必須爲文件的第一行,此前不能有任何內容,包括註釋。

消息使用「message」關鍵字定義,內部以「字段類型 字段名稱 = 字段序號;」形式定義所要包含額屬性。

一、序號:

每個字段被賦予一個惟一的序號,起始爲1不可重複。一般考慮到向後兼容的因素,不建議修改已定義的字段序號。

須要注意的是,序號大小會影響序列化編碼的空間佔用,例如:

序號範圍[1,15]:proto使用1個字節存儲字段的序號及類型,適宜定義經常使用字段。

序號範圍 [16,2047]:proto使用2個字節存儲字段的序號及類型。

...

序號可用域[1,229 - 1],其中[19000,19999]爲proto保留序號範圍(編譯使用),不可以使用。另外,開發方能夠約定保留序號,以供擴展或其它特殊使用。

二、字段約束

singular:更直觀的能夠用optional來釋義,可選字段,0個或1個,proto3中未默認約束。

repeated:列表集合字段類型,能夠包含 >=0 個字段元素。 

3、數據類型

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

 

4、默認值

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

 

5、枚舉

enum 枚舉對象 {

  UNKOWN = 0; //默認值機制使用(首先必須有一個枚舉值爲0的枚舉實例,其次兼容proto2中使用第一個變量爲默認值的機制)

  枚舉實例 = 枚舉值;

  ... ...

}

6、定義更新

一、不可修改已定義的字段序號。

二、能夠刪除已定義的字段,可是其序號不可在被使用。

三、int32, uint32, int64, uint64及bool是相互兼容的,只不過轉換過程會產生值域變動

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

五、byte3存儲值爲有效UTF-8編碼內容時與string相互兼容。

7、未知字段

未能對應解析的字段會存儲於未知字段中。此機制在proto3中最初拋棄,v3.5版本從新引入。

8、Map 類型

定義以下:

map<key_type, value_type> map_field = N。

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

value_type:能夠爲除了Map類型外的任何類型。

相關文章
相關標籤/搜索