https://blog.51cto.com/jackor/2997253
https://zhuanlan.zhihu.com/p/384953226?utm_id=0
这是一份很有诚意的 Protocol Buffer 语法详解
一、基础知识:
1.1 什么是rpc?rpc有什么作用
https://www.jianshu.com/p/7d6853140e13
1.2.protocol buffer 是什么
https://blog.csdn.net/mzpmzk/article/details/80824839
1.3.rpc的四种通信方式:
1.client/service 都是发送非stream的模式
2.client 发送非stream,service发送stream
3.client 发送stream,service发送非stream
4.client/service 都是发送stream的模式
1.4. 需要的python库
grpcio
grpcio-tools
protobuf
1.5、代码实现
1.5.1.proto文件
syntax = "proto3";
package test;
service Bilibili{
rpc HelloABiao(HelloABiaoRequest) returns (HelloABiaoResponse){}
}
message HelloABiaoRequest{
string name = 1;
int32 age = 2;
}
message HelloABiaoResponse{
string result = 1;
}
运行如下代码,生产pb2.py/pb2_grpc.py文件:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. hello_bilibili.proto
hello_bilibili_pb2.py
存的是request和response消息体
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: hello_bilibili.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14hello_bilibili.proto\x12\x04test\".\n\x11HelloABiaoRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03\x61ge\x18\x02 \x01(\x05\"$\n\x12HelloABiaoResponse\x12\x0e\n\x06result\x18\x01 \x01(\t2M\n\x08\x42ilibili\x12\x41\n\nHelloABiao\x12\x17.test.HelloABiaoRequest\x1a\x18.test.HelloABiaoResponse\"\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'hello_bilibili_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_globals['_HELLOABIAOREQUEST']._serialized_start=30
_globals['_HELLOABIAOREQUEST']._serialized_end=76
_globals['_HELLOABIAORESPONSE']._serialized_start=78
_globals['_HELLOABIAORESPONSE']._serialized_end=114
_globals['_BILIBILI']._serialized_start=116
_globals['_BILIBILI']._serialized_end=193
# @@protoc_insertion_point(module_scope)
hello_bilibili_pb2_grpc.py
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import hello_bilibili_pb2 as hello__bilibili__pb2
class BilibiliStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.HelloABiao = channel.unary_unary(
'/test.Bilibili/HelloABiao',
request_serializer=hello__bilibili__pb2.HelloABiaoRequest.SerializeToString,
response_deserializer=hello__bilibili__pb2.HelloABiaoResponse.FromString,
)
class BilibiliServicer(object):
"""Missing associated documentation comment in .proto file."""
def HelloABiao(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_BilibiliServicer_to_server(servicer, server):
rpc_method_handlers = {
'HelloABiao': grpc.unary_unary_rpc_method_handler(
servicer.HelloABiao,
request_deserializer=hello__bilibili__pb2.HelloABiaoRequest.FromString,
response_serializer=hello__bilibili__pb2.HelloABiaoResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'test.Bilibili', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class Bilibili(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def HelloABiao(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/test.Bilibili/HelloABiao',
hello__bilibili__pb2.HelloABiaoRequest.SerializeToString,
hello__bilibili__pb2.HelloABiaoResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
1.5.2 service.py
import time
import grpc
import hello_bilibili_pb2 as pb2
import hello_bilibili_pb2_grpc as pb2_grpc
from concurrent import futures
class Bilibili(pb2_grpc.BilibiliServicer):
def HelloABiao(self, request, context):
name = request.name
age = request.age
result = f'my name is {name}, i am {age} years old'
return pb2.HelloABiaoResponse(result=result)
def run():
grpc_server = grpc.server(
futures.ThreadPoolExecutor(max_workers=4)
)
pb2_grpc.add_BilibiliServicer_to_server(Bilibili(), grpc_server)
grpc_server.add_insecure_port('localhost:5000')
print("server will start at localhost:5000")
grpc_server.start()
try:
while True:
time.sleep(3600)
except KeyboardInterrupt:
grpc_server.stop(0)
if __name__ == '__main__':
run()
1.5.3 client.py
import grpc
import hello_bilibili_pb2 as pb2
import hello_bilibili_pb2_grpc as pb2_grpc
def run():
conn = grpc.insecure_channel('localhost:5000')
client = pb2_grpc.BilibiliStub(channel=conn)
response = client.HelloABiao(pb2.HelloABiaoRequest(
name="yingbiao.tian",
age=5
))
print(response.result)
if __name__ == "__main__":
run()
启动service.py
启动client.py
二、常用的protobuf数据类型和pb文件
2.1. 常用的protobuf数据类型
2.2常用的protobuf特殊字符
2.3 _pb2.py 文件介绍
每一个message对应的信息存储,比如我们的request与response在这里被定义extension
2.4_pb2_grpc.py 文件介绍
- ·用来存储每一个服务的server与客户端以及注册server的工具 ·
- 客户端名为: service_name + Stub
- 服务器名为: service_name + Servicer
- 注册服务为: add_服务端名_to_server
proto文件
syntax = "proto3";
package test;
service Bilibili{
rpc HelloABiao(HelloABiaoRequest) returns (HelloABiaoResponse){}
rpc HelloTest(stream HelloTestRequest) returns (HelloTestResponse){} //流的方式传送
}
message HelloABiaoRequest{
string name = 1;
int32 age = 2;
}
message HelloABiaoResponse{
string result = 1;
}
message HelloTestRequest{
string name1 = 1;
int64 age = 25;
repeated string data = 3;
map<string, HelloTestRequestNumberValue> number = 4; //string, int32, bool
}
message HelloTestRequestNumberValue{
string name = 1;
int32 age = 2;
bool is_active = 3;
}
message HelloTestResponse{
}