go中gRPC框架的使用初解|青训营笔记

140 阅读2分钟

这是我参与[第五届青训营]的第十六天

由于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生成客户端和服务代码。