当前位置:网站首页>【微服务系列】Protocol buffer动态解析
【微服务系列】Protocol buffer动态解析
2022-06-26 06:13:00 【shanxiaoshuai】
最近的工作中用到了grpc。之前工作中使用的是基于thrift的微服务框架,对grpc不是很熟悉,只知道grpc是一个基于http2和protobuf的rpc框架。但是使用方法都是大同小异的,基于idl生成相应的文件,服务端的话就实现具体的service并对外提供服务,客户端的话需要引入client包发起rpc调用。
这里有个问题,就是要调用下游的服务需要引入下游的client,如果下游服务的idl发生变动的话我们需要在代码中更新client包,重新编译部署发布。在常规的业务开发中这种模式是没什么问题的,发布部署的节奏是跟随业务迭代的节奏来的。但是在某些场景下可能存在比较大的问题,比如一个网关服务,网关上注册了很多的业务,网关通过rpc来调用业务服务。在这种情况下如果每次业务变更idl都需要网关随着发布部署那显然是问题很大的。
针对上面的问题进行了调研,发现可以使用动态解析idl文件的方式来解决问题。可以使用github.com/jhump/protoreflect来实现pb和grpc的反射。本来主要介绍pb部分的内容。
代码示例
建立简单的proto文件如下,其中定义了简单的结构体HelloReq和HelloResp。
syntax = "proto3";
package test;
option go_package = "data/";
message HelloReq {
int64 ID = 1;
string Name = 2;
}
message HelloResp {
int64 Code = 1;
string Message = 2;
}
按照一般的做法,这时应该执行protoc --go_out=. ./test.proto
命令生成test.pb.go,然后使用该结构体做相应的操作。
下面我们使用上面提到protoreflect包来进行运行时的解析,代码如下。
package main
import (
"encoding/json"
"github.com/jhump/protoreflect/desc/protoparse"
"github.com/jhump/protoreflect/dynamic"
"grpc_practice/data"
"log"
)
func main() {
// 创建parser对象
p := protoparse.Parser{
}
// 使用path的方式解析得到一些列文件描述对象,这里只有一个文件描述对象
fileDescs, err := p.ParseFiles("./test.proto")
if err != nil {
log.Printf("parse proto file failed, err = %s", err.Error())
return
}
// 从文件描述对象中根据消息名拿到消息藐视对象
helloReqDesc := fileDescs[0].FindMessage("test.HelloReq")
if helloReqDesc == nil {
log.Printf("no message matched")
return
}
// 根据消息描述对象生成动态消息
dMsg := dynamic.NewMessage(helloReqDesc)
// 使用该动态对象从GetHelloReq模拟的json对象解码
_ = dMsg.UnmarshalJSON(GetHelloReq())
log.Printf("req ID = %d, req Name = %s", dMsg.GetFieldByNumber(1), dMsg.GetFieldByNumber(2))
}
func GetHelloReq() []byte {
req := data.HelloReq{
}
req.ID = 1
req.Name = "xiaoshuai"
d, _ := json.Marshal(&req)
return d
}
原理解析
上面的demo还是比较简单的,看上面的代码不难发现核心的对象有两个,一是descriptor描述符,其对应了proto文件中的不同层级的对象;二是dynamicMessage动态消息,其代替了pb.go文件中的消息体。
简单来说的话,descriptor就是解析proto文件,并以数据结构的形式组织持有proto文件中的信息。dynamicMessage持有MessageDescriptor对象,就相当于了解该结构体所有信息。
Descriptor
不同层级的描述符的关系如下,没什么好详细展开的。
dynamicMessage
// Message is a dynamic protobuf message. Instead of a generated struct,
// like most protobuf messages, this is a map of field number to values and
// a message descriptor, which is used to validate the field values and
// also to de-serialize messages (from the standard binary format, as well
// as from the text format and from JSON).
type Message struct {
md *desc.MessageDescriptor
er *ExtensionRegistry
mf *MessageFactory
extraFields map[int32]*desc.FieldDescriptor
values map[int32]interface{
}
unknownFields map[int32][]UnknownField
}
dynamic message的源码如下,看到其主要的对象就是message descriptor,持有md对象dynamic message就拥有一个消息所有的信息,比如字段名称、序号、类型等。然后其值是存放在values这个map字段中,其值是以interface{}存放,所以用的时候会有大量的反射,后面会补充一些benchmark,观测其性能。
边栏推荐
- 06. talk about the difference and coding between -is and = = again
- zip(*arg)的用法
- 低代码实时数仓构建系统的设计与实践
- Logstash - logstash pushes data to redis
- 视图简析
- DPDK——TCP/UDP协议栈服务端实现(二)
- Pytorch uses multi GPU parallel training and its principle and precautions
- PyTorch混合精度原理及如何开启该方法
- Younger sister Juan takes you to learn JDBC -- two days' Sprint Day2
- Several promotion routines of data governance
猜你喜欢
Basic construction of SSM framework
PyTorch使用多GPU并行训练及其原理和注意事项
TCP连接与断开,状态迁移图详解
事务与消息语义
The sysdig 2022 cloud native security and usage report found that more than 75% of the running containers have serious vulnerabilities
TCP connection and disconnection, detailed explanation of state transition diagram
Younger sister Juan takes you to learn JDBC -- two days' Sprint Day2
Redis多线程与ACL
Alarm operation and Maintenance Center | build an efficient and accurate alarm collaborative processing system
Solve the problem that Cmdr cannot use find command under win10
随机推荐
Dpdk - tcp/udp protocol stack server implementation (II)
302. minimum rectangular BFS with all black pixels
Tortoise and rabbit race example
Design and practice of low code real-time data warehouse construction system
Unsatisfied dependency expressed through field ‘baseMapper‘; nested exceptio
SQL server functions
Failed to configure a DataSource: ‘url‘ attribute is not specified and no embedded datasource could
TCP connection and disconnection, detailed explanation of state transition diagram
Efk Upgrade to clickhouse log Storage Reality
China micro cultivator market trend report, technical dynamic innovation and market forecast
EFK昇級到ClickHouse的日志存儲實戰
Ppt template crawler case
Playing RTSP streaming video on Web pages (webrtc)
Print bit information of numbers
05. basic data type - Dict
架构设计方法
Gof23 - prototype mode
Implement the runnable interface
Play with a variety of application scenarios and share secrets with Kwai MMU
Handwritten background management framework template (I)