这是我参与[第五届青训营]的第十六天
由于JSON是一种文本格式,尽管在网页中使用的非常广泛,当发送数据过多时,序列化和反序列化的成本更高。虽然存在标准化的API规范(OpenAPI2.0或称Swagger2.0), 根据规范生成客户端服务端非常棘手。
gRPC一定程度上解决了这样的问题。由于它是二进制格式,发送速度更快,序列化反序列化速度更快,并且具有比JSON更好的类型。同时,gRPC的protoc工具具有广泛的代码生成能力。
协议缓冲区
使用 gRPC 的显着优势之一是协议缓冲区 (protobufs)。使用 protobufs,您可以将消息语义编码为客户端和服务器可以共享的可解析形式。此外,protobufs 是一种平台中立的语言,用于构建具有内置快速序列化和模式迁移支持的数据,如果您想在不引入停机时间的情况下更改消息格式,这是至关重要的。
首先创建消息:
syntax = "proto3";
package api.v1;
import "google/protobuf/timestamp.proto";
message Activity {
int32 id = 1;
google.protobuf.Timestamp time = 2;
string description = 3;
}
并安装protobuf编译器,使用它为消息类型生成go结构:
protoc activity-log/api/v1/*.proto \
--go_out=. \
--go_opt=paths=source_relative \
--proto_path=.
于是得到了可以在服务和客户端使用的活动结构:
package api_v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
type Activity struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Time *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=time,proto3" json:"time,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
}
protoc还生成了几个用于处理 protobuf 消息的辅助方法,例如字段获取器:
func (x *Activity) GetTime() *timestamppb.Timestamp {
if x != nil {
return x.Time
}
return nil
}
func (x *Activity) GetId() int32 {
if x != nil {
return x.Id
}
return 0
}
service Activity_Log {
rpc Insert(Activity) returns (InsertResponse) {}
rpc Retrieve(RetrieveRequest) returns (Activity) {}
rpc List(ListRequest) returns (Activities) {}
}
message RetrieveRequest {
int32 id = 1;
}
message InsertResponse {
int32 id = 1;
}
message ListRequest {
int32 offset = 1;
}
message Activities {
repeated Activity activities = 1;
}
message ActivityQuery {
int32 offset = 1;
}
并使用protoc生成客户端和服务代码。