跳到主要内容

gRPC

问题

什么是 gRPC?Go 中如何使用 gRPC?四种通信模式分别是什么?

答案

gRPC 简介

gRPC 是 Google 开源的高性能 RPC 框架,基于 HTTP/2Protocol Buffers

特性gRPCREST
协议HTTP/2HTTP/1.1 或 HTTP/2
序列化Protobuf(二进制)JSON(文本)
性能高(二进制 + 多路复用)较低
类型安全强(代码生成)
流式支持双向流有限(SSE)

Protocol Buffers

// user.proto
syntax = "proto3";
package user;
option go_package = "pb/user";

service UserService {
rpc GetUser(GetUserRequest) returns (User); // 一元 RPC
rpc ListUsers(ListUsersRequest) returns (stream User); // 服务端流
rpc CreateUsers(stream CreateUserRequest) returns (Summary); // 客户端流
rpc Chat(stream Message) returns (stream Message); // 双向流
}

message User {
int64 id = 1;
string name = 2;
string email = 3;
}

四种通信模式

Server 实现

type userServer struct {
pb.UnimplementedUserServiceServer
}

// 一元 RPC
func (s *userServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.User, error) {
user := findUser(req.Id)
if user == nil {
return nil, status.Errorf(codes.NotFound, "user %d not found", req.Id)
}
return user, nil
}

// 服务端流
func (s *userServer) ListUsers(req *pb.ListUsersRequest, stream pb.UserService_ListUsersServer) error {
users := getAllUsers()
for _, user := range users {
if err := stream.Send(user); err != nil {
return err
}
}
return nil
}

func main() {
lis, _ := net.Listen("tcp", ":50051")
grpcServer := grpc.NewServer()
pb.RegisterUserServiceServer(grpcServer, &userServer{})
grpcServer.Serve(lis)
}

拦截器(中间件)

// 一元拦截器
func loggingInterceptor(
ctx context.Context,
req any,
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (any, error) {
start := time.Now()
resp, err := handler(ctx, req)
log.Printf("method=%s duration=%v err=%v", info.FullMethod, time.Since(start), err)
return resp, err
}

server := grpc.NewServer(
grpc.UnaryInterceptor(loggingInterceptor),
)

常见面试问题

Q1: gRPC 和 REST 怎么选?

答案

  • 内部微服务通信:gRPC(高性能、类型安全、流式支持)
  • 公开 API / 浏览器直连:REST(兼容性好、调试方便)
  • 实时双向通信:gRPC 双向流

Q2: gRPC 的错误处理怎么做?

答案:使用 google.golang.org/grpc/statuscodes

return nil, status.Errorf(codes.NotFound, "user not found")
return nil, status.Errorf(codes.InvalidArgument, "name is required")

相关链接