背景:
需要对rpc服务进行压测,需要构造rpc请求。
protobuf 简介
Protocol Buffer (简称Protobuf) 是Google出品的性能优异、跨语言、跨平台的序列化库。
文档结构
protobuf 使用 .proto 文件来保存文档。
syntax = "proto3";
package cw.videoanalyze.alg_plugin;
message AlgPluginObject {
string plugin_name = 1; // 插件名称(必须要填写)
uint64 UOID = 2; // UOID (非必须)
string plugin_func = 3; // 插件方法
}
message AlgPluginRequest {
AlgPluginObject plugin = 1; // 插件对象
bytes serialize_data = 2; // 序列化数据(无关数据)
}
message AlgPluginResponse {
AlgPluginObject plugin = 1; // 插件对象
bool ret_flag = 2; // 响应结果
int32 error_no = 3; // 错误码,当ret_flag = false 时有用
string message = 4; // 返回消息
bytes serialize_data = 5; // 返回的序列化数据
}
/*
* 插件上报数据
* 说明: 该数据中包换了插件上报的所有的图片,抓拍坐标,属性等数据
*/
message AlgPluginReport {
AlgPluginObject plugin = 1; // 插件对象
string camera_id = 2; // 摄像头ID
bytes serialize_data = 3; // 序列化数据(无关数据)
}
/*
* 插件上报RPC接口
*/
service AlgReportPush {
rpc Report (AlgPluginReport) returns (AlgPluginResponse);
rpc Request (AlgPluginRequest) returns (AlgPluginResponse);
}
- protobuf 文档的第一行,为版本申明,不填写默认为版本2.
- package 定义proto的包名,包名可以避免对message 类型之间的名字冲突。也可省略。
- message 关键字定义消息。
- service 关键字定义服务。
定义消息
protobuf使用message定义消息,例如:
message AlgPluginObject {
string plugin_name = 1; // 插件名称(必须要填写)
uint64 UOID = 2; // UOID (非必须)
string plugin_func = 3; // 插件方法
}
AlgPluginObject消息定义了三个字段,分别为插件名称,U0ID及插件方法。
消息定义中的每个字段都有唯一的编号。这些字段编号用于以消息二进制格式标识字段,并且在使用消息类型后不应更改
定义服务
定义RPC方法,需要使用service关键字定义服务,并在里面定义方法。
/*
* 插件上报RPC接口
*/
service AlgReportPush {
rpc Report (AlgPluginReport) returns (AlgPluginResponse);
rpc Request (AlgPluginRequest) returns (AlgPluginResponse);
}
此处定义了一个AlgReportPush服务,包含两个rpc方法:
- Reprot 方法,入参为AlgPluginReport,返回参数为 AlgPluginResponse
- Request 方法,入参为AlgPluginRequest,返回参数为 AlgPluginResponse
下面针对上面的proto文件,写一个grpc client 进行rpc请求。
import grpc
import va_plugin_proto_pb2_grpc
import va_plugin_proto_pb2
import VideoObjectPush_pb2
def get_bytes():
img = 'D:\\10w\\1.jpg'
with open(img,'rb') as f:
bytes_data = f.read()
return bytes_data
def run():
# 连接RPC服务器
channel = grpc.insecure_channel('localhost:21001')
# 调用RPC服务
stub = va_plugin_proto_pb2_grpc.AlgReportPushStub(channel=channel)
#组装请求参数
alg_plugin_obj = va_plugin_proto_pb2.AlgPluginObject(plugin_name='videostream.person',plugin_func='videostream.person.return_callback')
box = VideoObjectPush_pb2.Box(x=1,y=1,width=1,height=1)
face = VideoObjectPush_pb2.Object(box=box,objPic=get_bytes(),qualityScore=0.656565,confidenceScore=0.13265,
pts=1546272000000)
person = VideoObjectPush_pb2.Person(objectId=1,cameraId="xiuxiqu",face=face)
object = VideoObjectPush_pb2.DetectedObject(person=person)
resp = stub.Report(va_plugin_proto_pb2.AlgPluginReport(plugin=alg_plugin_obj,camera_id='xiuxiqu',serialize_data=object.SerializeToString()))
print(resp)