gRPC项目学习总结
序列化对象为二进制和Json
Go
- 将protobuf信息写入二进制文件
- 从二进制文件中读取protobuf信息
- 写入json文件并比较大小
//json.go
// ProtobufToJson 将protobuf文件转换为json
func ProtobufToJson(message proto.Message) ([]byte, error) {
marshaler := protojson.MarshalOptions{
UseEnumNumbers: true, //枚举值使用数字
EmitUnpopulated: true, //未填充字段使用默认值
}
bin, err := marshaler.Marshal(proto.MessageV2(message))
if err != nil {
return nil, err
}
return bin, nil
}
//file.go
//序列化对象
// WriteProtobufToBinaryFile 将message对象序列化并写入二进制文件中
func WriteProtobufToBinaryFile(message proto.Message, filename string) error {
data, err := proto.Marshal(message) //序列化
if err != nil {
return err
}
if err = ioutil.WriteFile(filename, data, 0644); err != nil {
return err
}
return nil
}
gRPC 的四种通信方式
- 类似REST的单请求+单回复
- 客户端多请求+服务端单回复
- 客户端单请求+服务端多回复
- 客户端多请求+服务端多回复
service LaptopService {
//一元RPC 创建电脑
rpc CreateLaptop(CreateLaptopRequest) returns (CreateLaptopResponse){
option (google.api.http) = {
post: "/v1/laptop/create"
body: "*"
};
};
//服务器流式RPC 检索电脑
rpc SearchLaptop(SearchLaptopRequest) returns (stream SearchLaptopResponse){
option (google.api.http) = {
get: "/v1/laptop/search"
};
};
//客户端流式RPC 上传图片
rpc UploadLaptop(stream UploadLaptopRequest) returns (UploadLaptopResponse){
option (google.api.http) = {
post: "/v1/laptop/upload"
body: "*"
};
};
//双向流式RPC 评分
rpc RateLaptop(stream RateLaptopRequest) returns (stream RateLaptopResponse){
option (google.api.http) = {
post: "/v1/laptop/rate"
body: "*"
};
};
}
gRPC 反射
grpc反射
gRPC 服务器反射提供有关服务器上可公开访问的 gRPC 服务的信息,并帮助客户端在运行时构造 RPC 请求和响应,而无需预编译的服务信息。
它由 gRPC CLI 使用,可用于自省服务器原型和发送/接收测试 RPC。
evans
一个grpc客户端,在服务端开启反射并运行时,通过evans -r repl -p 端口
进入shell,
通过show package
查看反射的包信息,通过package 包名
选择不同的包,通过show service
查看反射的服务信息,通过service 服务
选择服务,通过call CreateLaptop
调用服务,中途使用ctrl+D
取消重复字段的输入…
evans
gRPC 拦截器
类似于中间件,可以在服务端和客户端之间添加的额外功能,服务器端拦截器是gRPC服务器在调用实际RPC方法前将调用的函数,可以用于日志记录,跟踪,限流,身份验证,限流等。
客户端拦截器是gRPC客户端在调用实际RPC方法前将调用的函数.
服务器端拦截器将采用JWT来验证,客户端拦截器将添加JWT到请求。
其实和go web 的token很像,都是注册到服务的前面,只不过方式不同而已。
// 拦截器的编写
const Authorization = "authorization"
//权限校验
type AuthInterceptor struct {
jwtMaker token.Maker
accessibleRoles map[string][]string //RPC对应的Roles
}
func NewAuthInterceptor(jwtMaker token.Maker, accessibleRoles map[string][]string) *AuthInterceptor {
return &AuthInterceptor{
jwtMaker: jwtMaker, accessibleRoles: accessibleRoles}
}
// Unary 一元拦截器
func (interceptor *AuthInterceptor) Unary() grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{
}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{
}, err error) {
log.Println("-->unary Interceptor: ", info.FullMethod)
if err := interceptor.authorized(ctx, info.FullMethod); err != nil {
return nil, err
}
return handler<