我們知道接口傳輸數據的格式有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
的字段必須要聲明是required
,repeated
,optional
。
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
我幫你問:這有什么用?
想想當你在發送數據的時候,以 序列化的數據發送,是不是更節省資源?是不是更安全?