protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法
它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法
可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码
轻松的在各种数据流中使用各种语言进行编写和读取结构数据。
你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
protobuf通过定义包含类型结构序列化信息的文件(.proto文件),来编译生成不同语言平台的高效序列化程序代码
根据不同系统下载不同protoc编译器,在windows下下载windows后缀的 protoc-3.12.0-rc-1-winxxx.zip 解压后得到的目录中,bin目录中的protoc.exe就是编译protoc代码命令
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/5/5 1:24 bin
d----- 2020/5/5 1:24 include
-a---- 2020/5/5 1:24 724 readme.txt
把protoc.exe配置到Path环境变量
protoc --python_out=$DST_DIR $SRC_DIR/your.proto
其中,DST_DIR指定编译的go代码输出路径,SRC_DIR/your.proto指定proto文件,最后一个参数是要编译的proto文件名 最终生成了代码文件xxx_pb2.py
一般在proto文件开头使用syntax声明proto版本,默认是proto2 比如
syntax = "proto3";
通过import语句导入proto包,比如
import "google/protobuf/struct.proto"
protobuf中使用关键字message定义结构,并且结构中可以嵌套定义结构,比如
message A {}
message B {
message C {
}
}
每个message最终会被解释为一个类,通过该类生成支持protobuf序列化的实例
A = _reflection.GeneratedProtocolMessageType(... ..)
_sym_db.RegisterMessage(A)
B = _reflection.GeneratedProtocolMessageType(... ..)
_sym_db.RegisterMessage(B)
_sym_db.RegisterMessage(B.C)
接下来就可以导入使用
from test_pb2 import *
a = A()
print(a.SerializeToString())
c = B.C()
print(c.SerializeToString())
基本定义语法如下,其中type是类型,name是字段名称,num是数据编号 当反序列化时,会把对应数据编号对应的数据填充到对应字段 对于type,如果是message类型,在生成实例时,对应字段会自动构造一个对应message序列化类型的实例,并禁止修改(只能对该属性实例的字段赋值,而不能修改该属性绑定其他实例)
type name = num
message A {
string name = 1;
}
message B {
string name = 1;
}
message A {
B b = 1;
}
message A {
map<string,int> pic = 1;
}
message A{
enum Color{
RED = 0;
BLACK = 1;
}
Color c = 1;
}
enum Day{
ONE = 0;
TWO = 1;
}
message B{}
message A{
repeated B bs= 1;
}
类似的,repeated属性也是在实例化时自动构造空数组,并禁止对属性赋值,只能操作数组往里面增删元素,且元素类型必须符合指定的类型
proto支持通过service与rpc关键字分别定义rpc服务和rpc方法,proto默认不会生成rpc代码,需要结合对应的rpc插件(grpc、twirp等)编译才会生成 比如如下代码,定义了一个service,提供一个search的rpc调用方法,接收一个Request类型的参数,返回Response类型的结果
message Request{}
message Response{}
service Search{
rpc search(Request) returns(Response);
}
需要先安装python相关的grpc模块(下面使用国内镜像)
pip install grpcio-tools -i https://pypi.tuna.tsinghua.edu.cn/simple
然后使用grpc模块结合protobuf生成对应的rpc的server和client
python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. test.proto
这时发现本次proto编译比上次多了一个test_py2_grpc.py,包含rpc的内容 里面提供XXXServicer类,具备对应的映射方法抛出异常(提示需要你去重写映射后的处理和返回结果) 然后还有一个add_XXXServicer_to_server方法,第一个参数接收上面XXXService的一个实例对象,第二个参数接收一个grpc.Server的对象,也就是继承XXXService类,重写映射处理方法,实例化一个子类对象,利用提供的add_XXXServicer_to_server,把该子类对象添加到对应的grpc.Server对象,则可以完成添加rpc方法到grpcServer中