背景:
需要對rpc服務進行壓測,需要構造rpc請求。
protobuf 簡介
Protocol Buffer (簡稱Protobuf) 是Google出品的性能優(yōu)異、跨語言、跨平臺的序列化庫。
文檔結構
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; // 序列化數(shù)據(jù)(無關數(shù)據(jù))
}
message AlgPluginResponse {
AlgPluginObject plugin = 1; // 插件對象
bool ret_flag = 2; // 響應結果
int32 error_no = 3; // 錯誤碼,當ret_flag = false 時有用
string message = 4; // 返回消息
bytes serialize_data = 5; // 返回的序列化數(shù)據(jù)
}
/*
* 插件上報數(shù)據(jù)
* 說明: 該數(shù)據(jù)中包換了插件上報的所有的圖片,抓拍坐標,屬性等數(shù)據(jù)
*/
message AlgPluginReport {
AlgPluginObject plugin = 1; // 插件對象
string camera_id = 2; // 攝像頭ID
bytes serialize_data = 3; // 序列化數(shù)據(jù)(無關數(shù)據(jù))
}
/*
* 插件上報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 方法,入?yún)锳lgPluginReport,返回參數(shù)為 AlgPluginResponse
- Request 方法,入?yún)锳lgPluginRequest,返回參數(shù)為 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)
#組裝請求參數(shù)
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)