gRPC深入解析

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 编译器生成的其他代码

包括字节流输入输出对象的转化过程代码;

发布了93 篇原创文章 · 获赞 20 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/leinminna/article/details/104395830