gRPC
使用
本例使用proto3来写一个常见的用户登录与注册的gRPC的服务端
FieldMask在以下场景中非常有用:
- 更新部分字段:当您需要更新消息中的部分字段而不是整个消息时,可以使用
FieldMask来指定要更新的字段。 - 减少数据传输:在客户端与服务器之间传输消息时,可以使用
FieldMask来减少数据传输的大小,只传输需要更新的字段,而不是整个消息。 - 精细化控制:通过使用
FieldMask,客户端可以对更新操作进行精细化控制,只更新特定的字段,而不影响其他字段的数值。
总之,google.protobuf.FieldMask提供了一种灵活的方式来指定消息中需要更新的字段,从而在通信和数据更新方面提供了更高的效率和精细化控制。
google.protobuf.FieldMask mask = 2;定义proto
syntax = "proto3";
package users;option go_package = "proto/user";
message LoginRequest { string username = 1; string password = 2;}
message LoginResponse { int32 state_code =1; string state_msg = 2;}
message RegisterRequest { string username = 1; string password = 2;}
message RegisterResponse { int32 state_code =1; string state_msg = 2;}
enum Gender { SEX = 0; MAN =1; WOMEN = 2;}
message User { string name = 1; int32 age = 2; Gender gender = 3;}
service UserService { rpc Login(LoginRequest) returns(LoginResponse); rpc Register(RegisterRequest) returns(RegisterResponse);}定义rpc服务
proto: https://github.com/googleapis/googleapis
rpc 有四种服务:
- 一元RPC:
service User { rpc Login(LoginRequest) returns(LoginResponse)}- 服务器流式RPC
service Steam { rpc Video(VideoRequest) returns(steam VideoSteam)}- 客户端流式RPC
service Steam { rpc Video(steam VideoSteam) returns(VideoResponse)}- 双向流式RPC
service Steam { rpc Video(steam VideoSteam) returns(steam VideoSteam)}选项:
rpc与http方法的映射, 以达到 HTTP 可以访问 rpc 服务
service User { rpc Login(VideoRequest) returns(steam VideoSteam) { option (google.api.http) = { post: "/user/login" } }}生成pb文件
- 生成在
proto的目录下
protoc -I=. --go_out=proto --go-grpc_out=proto */*.proto目录结构:
├── proto│ └── user│ └── user.pb.go├── protobuf│ └── user.proto- 生成在原始(即源文件)的目录下
protoc -I=. --go_out=. --go_opt=paths=source_relative \--go-grpc_out=. --go-grpc_opt=paths=source_relative \*/*.proto目录结构:
├── protobuf│ ├── user.pb.go│ └── user.protogrpc的service服务的文件也同--go_out的所在目录
protoc -I=. --go_out=. --go-grpc_out=. */*.proto目录结构
├── proto│ └── user│ ├── user.pb.go│ └── user_grpc.pb.go├── protobuf│ └── user.proto创建服务器
- 从定义生成的 rpc 服务中, 编写对应服务接口
type User { Username string Password string}
func (User) Login(ctx context, username password *pb.User) (*pb.Response, error){
}启动服务器
- 监听客户端请求
- 创建
prpc示例 - 向
grpc服务器注册我们的服务实现 - 启动服务, 调用
Server()阻塞等待, 直到进程被终止或Stop()调用
// 1. 启动 tcp 服务, 监听客户端请求lisn, err := net.Listen("tcp", "localhost:8080")if err != nil{ log.Fatalf("failed to listen: %v", err)}
// rpc opts 选项var opts []grpc.ServerOption...// 2. 创建`prpc`示例grpcServer := gprc.NewServer(opts)
// 3. 向`grpc`服务器注册我们的服务实现pb.RegisterServer(grpcServer,NewServer())
// 4. 启动grpc服务, 基于 http2.0的I/O多路复用grpcServer.Server(lis)创建客户端
- 创建 grpc 通道(可以在
grpc.Dial时设置身份验证凭据(例如 TLS、GCE或 JWT )
var opts []grpc.DialOption...conn, err := grpc.Dial(*serverAddr, opts...)if err != nil { ...}defer conn.Close()- 调用服务端方法, 方法名为
user.pb文件中定义的New+服务名+Client, 本例定义的服务名为serService, 即对应的客户端的方法为:NewUserServiceClient
client := user.NewUserServiceClient(conn)