1 前言
gRPC实现客户端和服务端的服务的扭转,具体实现了微服务的分布式和接口的跨语言调用。
他的关键部分proto buffers,proto buffers 的工作原理解析如下:
2 定义服务
proto buffers 定义公共方法和传输对象
syntax = "proto3";
option java_package = "cc.iooc.common.rpc.snowflake.proto";
option java_multiple_files = true;
package proto;
// 定义的服务方法编译后,客户端和服务端将会生成不同的的方法;
// 客户端:生成客户对象,并生成该方的客户端接口并内部实现,用于调用;
// 服务端:生成服务端接口,没有实现,供服务度的业务层实现;
// 具体的代码实例见下;
service Snowflake {
rpc GetID (SnowflakeRequest) returns (SnowflakeResponse) {
}
}
// 这里下面的... ,参考https://developers.google.cn/protocol-buffers/docs/proto?hl=en#updating
// 对象中的数字有规定,每个对象中的不同属性,数字唯一...
// 对象中的每个字段,前面可以添加optional/required/repeated属性...
// 对象中每个字段的类型,有规定参考...
// 这两个对象将会编译后生成在.pb.go中生成,供客户端和服务端共同使用。
message SnowflakeRequest { // 定义一个请求对象,封装接口请求参数
int32 count = 1;
optional string messs = 2;
}
message SnowflakeResponse { // 定义一个相应对象,封装接口相应参数
repeated string ids = 1;
string replee = 2;
}
3 服务扭转
编译生成方法和传输对象在客户端和服务端方法中的使用对比分析
3.1 客户端调用proto buffers 提供的方法
func (s *SnowflakeGRPCClient) GetName(mess string) string {
// 到grpc连接池获取当前客户的grpc连接
conn, err := rpc.GetConn(s.Address)
if err != nil {
log.Errorf("snowflake client: %v", err)
return "nil"
}
// 方法最后,关闭连接
defer rpc.Close(s.Address, conn)
response, err := func(conn *grpc.ClientConn) (interface{}, error) {
// 调用proto buffers 生成的客户端对象;提供了在.proto文件中我们之前定义的方法,也是我们需要的方法。
client := proto.NewSnowflakeClient(conn)
// 调用grpc生成的接口及其实现方法
// 给proto生成的请求对象(SnowflakeRequest)的属性(Mess)设置值
response, err := client.GetName(context.Background(), &proto.SnowflakeRequest{Messs: mess})
return response, err
}(conn)
if err != nil {
log.Error(err)
return "nil"
}
// 从生成的相应对象(SnowflakeResponse)中获取属性值(Replee)作为返回值
return response.(*proto.SnowflakeResponse).Replee
}
3.2 服务端调用proto buffers 提供的方法
func (s *SnowflakeGRPCServer) GetName(ctx context.Context, request *proto.SnowflakeRequest) (*proto.SnowflakeResponse, error) {
response := new(proto.SnowflakeResponse)
if request.Messs != "" {
if replee, err := service.GetName(request.Messs); err == nil {
response.Replee = replee
} else {
return nil, err
}
} else {
return nil, errors.New("The count should greater than 0!")
}
return response, nil
}
4 解析proto buffers
proto buffers 生成的关键方法和对象展示
4.1 proto buffers 生成的客户端和服务端都需要的方法和对象
// 生成请求参数封装对象
type SnowflakeRequest struct {
Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"`
Messs string `protobuf:"bytes,2,opt,name=messs,proto3" json:"messs,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
// 生成响应参数封装对象
type SnowflakeResponse struct {
Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"`
Replee string `protobuf:"bytes,2,opt,name=replee,proto3" json:"replee,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
4.2 proto buffers 生成的客户端需要的方法和对象
// 生成客户端接口方法
type SnowflakeClient interface {
GetName(ctx context.Context, in *SnowflakeRequest, opts ...grpc.CallOption) (*SnowflakeResponse, error)
}
// 该接口的实现方法也在此处生成了,冗余,暂时不列出
// 生成请求客户端对象
type snowflakeClient struct {
cc *grpc.ClientConn
}
// 生成请求客户端对象,构造方法
func NewSnowflakeClient(cc *grpc.ClientConn) SnowflakeClient {
return &snowflakeClient{cc}
}
4.3 proto buffers 生成的服务端需要的方法和对象
// 只是定义服务端的接口,然后服务端实现这些定义的接口,这些接口与.proto中的接口一致
type SnowflakeServer interface {
GetName(context.Context, *SnowflakeRequest) (*SnowflakeResponse, error)
}
4.4 编译器生成的其他代码
包括字节流输入输出对象的转化过程代码;