用途
本资料面向服务间通信场景,讲解 gRPC 与 Protocol Buffers 的使用。它给出 Protobuf 模式定义、代码生成、四种调用模式以及多语言实现示例,适合需要构建内部微服务 API 的开发者。
Protobuf 基础
Protocol Buffers 是一种语言中立的二进制序列化格式,模式定义写在 .proto 文件中。示例采用 proto3 语法,定义 package、go_package 选项,以及 message(包含字段编号、repeated 列表、嵌套 message、enum、map)和 enum(要求零值)。
标量类型映射示例:double 对应 Go float64、Python float、Node number、Java double;float 对应 float32/float/number/float;int32 对应 int32/int/number/int;int64 对应 int64/int/number/long;bool 对应 bool/bool/boolean/boolean;string 对应 string/str/string/String;bytes 对应 []byte/bytes/Buffer/ByteString。
资料建议:字段编号 1-15 在传输中占一个字节,保留给高频字段;字段编号不可复用;使用包装类型(如 google.protobuf.StringValue)区分未设置与默认值。
服务定义
服务在 .proto 中用 service 定义,示例 UserService 包含四种 rpc:GetUser 为一元调用,ListUsers 为服务端流,UploadUsers 为客户端流,SyncUsers 为双向流。请求与响应 message 随服务一同定义。
代码生成
安装方式:macOS 使用 brew install protobuf,Linux 使用 apt install protobuf-compiler。 生成命令示例:Go 用 protoc --go_out=. --go-grpc_out=. proto/user.proto;Python 用 python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. proto/user.proto;Node.js 用 grpc_tools_node_protoc --js_out=import_style=commonjs:. --grpc_out=. proto/user.proto。
buf 作为现代 protoc 替代方案,示例配置包括 buf.yaml(版本、模块路径、lint、breaking)与 buf.gen.yaml(远程插件、输出目录、选项)。命令为 buf lint、buf breaking --against '.git#branch=main'、buf generate。buf 强制风格:包名与目录匹配、枚举零值以 _UNSPECIFIED 结尾、服务名以 Service 结尾。
gRPC 调用模式
一元:一请求一响应,用于 CRUD、查询。服务端流:一请求多响应,用于大结果集、数据流。客户端流:多请求一响应,用于上传、批量导入。双向流:双方独立流式传输,用于聊天、实时同步。
多语言实现示例
资料给出 Node.js 使用 @grpc/grpc-js 与 @grpc/proto-loader 的加载配置、服务端处理函数 getUser/listUsers、Server 绑定端口,以及客户端一元调用与流式监听;Python 使用 grpc 与 concurrent.futures 定义 Servicer、实现 GetUser(含 context.abort 参数校验)与流式 ListUsers、启动 server,以及客户端 stub 调用与超时、错误处理;Go 定义 server 结构体、实现 GetUser(status.Error 校验)与流式 ListUsers(stream.Send)、main 注册并监听,以及客户端 grpc.Dial 与超时 context。
测试工具 grpcurl
安装:brew install grpcurl。使用要求服务端开启 reflection,或通过 -import-path/-proto 指定。示例命令包括 list 列出服务、describe 描述服务、-d 传入请求体调用方法、-H 传元数据、以及带 import-path 与 proto 的流式调用。启用 reflection 的方式:Go 用 reflection.Register(s),Python 用 grpc_reflection.v1alpha.reflection.enable_server_reflection(names, server),Node 用 @grpc/reflection。
错误处理状态码
表列常见状态码及用途:OK(0) 成功;CANCELLED(1) 客户端取消;INVALID_ARGUMENT(3) 输入错误;DEADLINE_EXCEEDED(4) 超时;NOT_FOUND(5) 资源缺失;ALREADY_EXISTS(6) 创建冲突;PERMISSION_DENIED(7) 无权限;RESOURCE_EXHAUSTED(8) 限流/配额;FAILED_PRECONDITION(9) 系统状态不符;UNIMPLEMENTED(12) 方法未实现;INTERNAL(13) 服务器意外错误;UNAVAILABLE(14) 瞬时故障可重试;UNAUTHENTICATED(16) 无有效凭据。资料提示不要用 UNKNOWN 兜底,瞬时故障应返回 UNAVAILABLE 以便客户端重试。
元数据、超时与健康检查
元数据相当于 HTTP 头,键为字符串,二进制值使用以 -bin 结尾的键。资料给出 Go 读取 incoming metadata 与追加 outgoing metadata,以及 Python 读取 invocation_metadata 与发送 metadata 的写法。 超时应始终设置并传播上下文,示例包括 Go context.WithTimeout、Python timeout=5、Node deadline 计算。 健康检查使用标准 grpc.health.v1.Health 协议,Go 示例注册 health server 并设置服务状态,可用 grpcurl 调用 Health/Check。
常见模式与 gRPC 对比 REST
微服务 API 结构示例按 proto/myapp 下按 user/v1、order/v1 组织 proto 文件,请求/响应随服务,共享领域消息通过 import,包名用 v1 后缀做版本管理。流式数据示例 PriceFeed 提供 Subscribe 返回 PriceUpdate 流,客户端在 UNAVAILABLE 时以指数退避重连,并用 keepalive 检测死连接。 对比表从序列化、模式、流式、浏览器、工具、性能、代码生成、负载均衡等维度比较 gRPC 与 REST:gRPC 使用二进制 Protobuf、必需 .proto、原生四种流、浏览器需 grpc-web 代理、工具为 protoc/buf 加插件、延迟更低载荷更小、内置强类型代码生成、需 L7 HTTP/2 感知负载均衡;REST 使用 JSON 文本、OpenAPI 可选、流式需 SSE/WebSocket 变通、浏览器原生、工具为 curl 与任意 HTTP 客户端、延迟与载荷更高、代码生成不一、任意 HTTP 负载均衡器可用。资料建议内部服务间调用用 gRPC,公开 API 与浏览器客户端用 REST,两者可共存,边缘用 REST、内部用 gRPC。
限制
资料未提供具体的适用环境版本、性能基准数字、许可信息或收费说明。