protocol buffer 基礎


我們知道接口傳輸數據的格式有XML,它是 web services 使用的傳輸數據的格式,在web services 中叫 WSDL。

https://www.w3school.com.cn/wsdl/index.asp

不過 web Services 已經是被淘汰的技術了。

現在更是主流的是使用JSON作為數據傳輸格式。HTTP + JSON是黃金搭檔。

什么是protocol buffer

protocol buffer是一種與語言和平台無關。

Protocol Buffer是用於結構化數據串行化的靈活、高效、自動的方法,有如XML,不過它更小、更快、也更簡單。你可以定義自己的數據結構,然后使用代碼生成器生成的代碼來讀寫這個數據結構。你甚至可以在無需重新部署程序的情況下更新數據結構。

protocol buffer 是如何使用

  • 定義 xx.proto文件,即 接口數據格式。
  • 使用 proto 命令生成對應語言腳本。
  • 通過語言腳本設置接口要發送/接收的數據。

定義 .proto 文件,

創建一個foo.proto 文件中定義你需要做串行化的數據結構信息。每個ProtocolBuffer信息是一小段邏輯記錄,包含一系列的鍵值對。

這里定義一個簡單的 foo.proto 文件定義了個人信息:

syntax = "proto2";
package info;

message Person {
    required string name=1;
    required int32 id=2;
    optional string email=3;

    enum PhoneType {
        MOBILE=0;
        HOME=1;
        WORK=2;
    }

    message PhoneNumber {
        required string number=1;
        optional PhoneType type=2 [default=HOME];
    }

    repeated PhoneNumber phone=4;
}

這個信息就是你的接口要發送的數據格式。

文件說明:

syntax = "proto2";

文件最開始建議說明使用proto2還是proto3語法的聲明。

package info;

文件必須以 package xxxx; 聲明開頭,作為協議唯一的標識,避免不同項目的命名沖突,你可以理解成我給一個人起名叫張三,如果要想找這個人,就要叫一聲張三。

message Person {
    ...
    message PhoneNumber {
        ...
    }
}

一個 message 相當於一個指定類型的集合,例如 bool, int32, float, double ,string 這些類型都是可以直接使用在proto協議中的某個message當中指定數據類型的。

一個message可以直接嵌套另一個message使用,被嵌套的message就相當於string一樣,被認為是一種數據類型。

required string name=1;
required int32 id=2;
optional string email=3;
...
repeated PhoneNumber phone=4;

每個message的字段必須要聲明是requiredrepeatedoptional

Required: 表示是一個必須字段,必須相對於發送方,在發送消息之前必須設置該字段的值,對於接收方,必須能夠識別該字段的意思。發送之前沒有設置required字段或者無法識別required字段都會引發編解碼異常,導致消息被丟棄。

Optional:表示是一個可選字段,可選對於發送方,在發送消息時,可以有選擇性的設置或者不設置該字段的值。對於接收方,如果能夠識別可選字段就進行相應的處理,如果無法識別,則忽略該字段,消息中的其它字段正常處理。因為optional字段的特性,很多接口在升級版本中都把后來添加的字段都統一的設置為optional字段,這樣老的版本無需升級程序也可以正常的與新的軟件進行通信,只不過新的字段無法識別而已,因為並不是每個節點都需要新的功能,因此可以做到按需升級和平滑過渡。

Repeated:表示該字段可以包含0~N個元素。其特性和optional一樣,但是每一次可以包含多個值。可以看作是在傳遞一個數組的值。

好了,你現在對 .proto 文件的定義有了大概的一個了解了。

使用 proto 命令生成對應語言腳本

1、下載 protobuf 文件

https://github.com/protocolbuffers/protobuf/releases

以windows為例,下載下面兩個文件:

  • protobuf-python-3.12.3.zip

  • protoc-3.12.3-win64.zip

2、 先解壓 protobuf-python-3.12.3.zip 文件,得到 protobuf-3.12.3目錄,再解壓 protoc-3.12.3-win64.zip 文件得到 protoc 目錄,把你 protoc 目錄放到 protobuf-3.12.3目錄。

3、 設置環境變量path

D:\pybase\protobuf-3.12.3\protoc\bin

將上面的路徑添加環境變量。

4、 執行 proto 命令,生成python腳本。利用前面創建 foo.proto 文件。

protoc --python_out=. foo.proto

你會看到同目錄下多出一個 foo_pb2.py 的文件。不用打開看了,反正你也看不懂。

通過語言腳本設置接口要發送/接收的數據

現在我們利用 foo_pb2.py 文件定義發送的接口數據。 創建一個test_foo_pb2.py文件。

import foo_pb2


def set_info(info_):
    info_.id = 1
    info_.name = "tom"
    info_.email = "tom@gmail.com"

    phone = info_.PhoneNumber
    phone.phone = 400100
    phone.type = 2

    return info_


info = foo_pb2.Person()

one_info = set_info(info)
print("設置數據:\n", one_info)

proto_info = one_info.SerializeToString()
print("序列化:\n", proto_info)


def get_info(wanted_info):
    """
    反序列化的數據
    """
    print("反序列化:\n")
    wanted_id = wanted_info.id
    print("info id:", wanted_id)
    print("his age: ", wanted_info.name)

    print("his phone number :", wanted_info.PhoneNumber.phone)
    print("his phone type :", wanted_info.PhoneNumber.type)


first_parsed = foo_pb2.Person()
first_parsed.ParseFromString(proto_info)
get_info(first_parsed)

打印結果:

設置數據:
 name: "tom"
id: 1
email: "tom@gmail.com"

序列化:
 b'\n\x03tom\x10\x01\x1a\rtom@gmail.com'
 
反序列化:
info id: 1
his age:  tom
his phone number : 400100
his phone type : 2

我幫你問:這有什么用?

想想當你在發送數據的時候,以 序列化的數據發送,是不是更節省資源?是不是更安全?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM