gRPC 入门指南

2026-06-22 · 6 阅读 · 424字
API设计Go微服务

gRPC 入门指南

什么是 gRPC

gRPC 是由 Google 开源的高性能 RPC 框架,基于 HTTP/2 和 Protocol Buffers。它支持多种编程语言,提供双向流、流控、认证等特性。

Protocol Buffers

定义服务

使用 .proto 文件定义服务和消息结构:

syntax = "proto3";

package user;

service UserService {
    rpc GetUser (GetUserRequest) returns (User);
    rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);
    rpc UpdateUser (UpdateUserRequest) returns (User);
    rpc WatchUser (WatchUserRequest) returns (stream UserEvent);
}

message GetUserRequest {
    string user_id = 1;
}

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

message ListUsersRequest {
    int32 page = 1;
    int32 page_size = 2;
}

message ListUsersResponse {
    repeated User users = 1;
    int32 total = 2;
}

数据类型

.proto 类型 Go 类型 Java 类型 说明
double float64 double 64位浮点
float float32 float 32位浮点
int32 int32 int 变长编码
int64 int64 long 变长编码
string string String UTF-8 字符串
bytes []byte ByteString 字节数组

四种通信模式

一元 RPC(Unary)

请求-响应模式,类似传统 HTTP:

rpc GetUser(GetUserRequest) returns (User);

服务端流式

服务端持续发送数据流:

// 服务端
func (s *server) WatchUser(req *pb.WatchUserRequest, stream pb.UserService_WatchUserServer) error {
    for {
        event := getUserEvent(req.UserId)
        if err := stream.Send(event); err != nil {
            return err
        }
        time.Sleep(1 * time.Second)
    }
}

客户端流式

客户端持续发送数据流:

rpc UploadLogs(stream LogEntry) returns (UploadResponse);

双向流式

双方可以独立发送数据:

rpc Chat(stream ChatMessage) returns (stream ChatMessage);
func (s *server) Chat(stream pb.ChatService_ChatServer) error {
    for {
        msg, err := stream.Recv()
        if err == io.EOF {
            return nil
        }
        if err != nil {
            return err
        }
        // 处理消息并回复
        stream.Send(&pb.ChatMessage{...})
    }
}

gRPC vs REST

特性 gRPC REST
协议 HTTP/2 HTTP 1.1/2
数据格式 Protocol Buffers(二进制) JSON/XML(文本)
接口定义 强类型(.proto) 无标准(常用 OpenAPI)
流式通信 原生支持 需 WebSocket
浏览器支持 需 gRPC-Web 原生
调试工具 需特殊工具 curl / Postman
性能 高(二进制 + HTTP/2) 中等

中间件(Interceptor)

// 服务端拦截器:日志记录
func loggingInterceptor(ctx context.Context, req interface{},
    info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    log.Printf("gRPC call: %s", info.FullMethod)
    start := time.Now()
    resp, err := handler(ctx, req)
    log.Printf("gRPC call %s completed in %v", info.FullMethod, time.Since(start))
    return resp, err
}

// 注册拦截器
server := grpc.NewServer(
    grpc.UnaryInterceptor(loggingInterceptor),
)

最佳实践

  • 使用 google/protobuf/wrappers.proto 处理可选字段
  • 合理设置消息大小限制(默认 4MB)
  • 启用 gzip 压缩减少带宽
  • 使用健康检查协议实现服务探活
  • 谨慎设计 proto 文件,字段号一旦发布不宜修改