Go gRPC 实战:从 proto 到流式 RPC 全链路
gRPC 是微服务通信的事实标准,性能是 HTTP/JSON 的 5-10 倍。本文从 IDL 到流式调用一次性讲透。
一、安装 protoc
goinstallgoogle.golang.org/protobuf/cmd/protoc-gen-go@latest goinstallgoogle.golang.org/grpc/cmd/protoc-gen-go-grpc@latest写入.proto文件:
syntax = "proto3"; package user.v1; option go_package = "example.com/user/proto;userpb"; service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc ListUsers(ListUsersRequest) returns (stream User); } message User { string id = 1; string name = 2; int32 age = 3; } message GetUserRequest { string id = 1; } message GetUserResponse { User user = 1; } message ListUsersRequest {}执行:protoc --go_out=. --go-grpc_out=. user.proto
二、四个调用模式
- Unary:标准 RPC(客户端发、收一次)
- Server Streaming:服务器流式推送
- Client Streaming:客户端流式推送
- Bidirectional Streaming:双向流式
三、Server 实现
import("google.golang.org/grpc"userpb"example.com/user/proto")typeserverstruct{userpb.UnimplementedUserServiceServer}func(s*server)GetUser(ctx context.Context,req*userpb.GetUserRequest)(*userpb.GetUserResponse,error){return&userpb.GetUserResponse{User:&userpb.User{Id:req.Id,Name:"tom",Age:18}},nil}func(s*server)ListUsers(req*userpb.ListUsersRequest,stream userpb.UserService_ListUsersServer)error{for_,u:=rangerepo.All(){iferr:=stream.Send(u);err!=nil{returnerr}}returnnil}funcmain(){lis,_:=net.Listen("tcp",":50051")s:=grpc.NewServer(grpc.UnaryInterceptor(recoverInterceptor()))userpb.RegisterUserServiceServer(s,&server{})s.Serve(lis)}四、Client 实现
conn,err:=grpc.Dial(":50051",grpc.WithInsecure())deferconn.Close()cli:=userpb.NewUserServiceClient(conn)ctx,cancel:=context.WithTimeout(context.Background(),time.Second)defercancel()u,err:=cli.GetUser(ctx,&userpb.GetUserRequest{Id:"42"})// 流式stream,err:=cli.ListUsers(ctx,&userpb.ListUsersRequest{})for{u,err:=stream.Recv()iferr==io.EOF{break}iferr!=nil{returnerr}fmt.Println(u)}五、拦截器链路
grpc.UnaryServerInterceptor(loggingInterceptor,recoverInterceptor,traceInterceptor,)跨多拦截器时,用 go-grpc-middleware 库。
六、性能压测
BenchmarkGRPC-8 100000 14000 ns/op 400 B/op 2 allocs/op BenchmarkJSON-8 50000 28000 ns/op 1200 B/op 9 allocs/opgRPC 性能明显占优。
七、踩坑清单
- ctx 必须传:否则无法超时与取消
- Default 流量是 TCP 不加密:在线环境用 TLS
- 大消息拆流式:proto 序列化包含大值时,单个 message 不要过大
- 字段编号不能修改:旧字段只能 deprecated + 新字段
八、总结与展望
gRPC 是云原生时代服务通信的最佳实践。掌握 proto、stream、interceptor 三件套,能构建高性能微服务集群。
未来:grpcurl + buf schema 工具链 + Connect 等兼容 HTTP/JSON 的形态值得关注。
九、参考文献
- gRPC 官方文档:https://grpc.io/
- protobuf-go 文档
- grpcurl 工具