gRPC 开发者快速入门
精简版快速入门,只保留核心概念与上手步骤。
目录
- 一句话了解 gRPC
- 核心概念(4 步)
- 四种 RPC 类型
- 5 分钟上手(以 Python 为例)
- 错误处理与超时
- 元数据(Metadata)
- 同步 vs 异步
- 安全速览
- 特性一览
- 何时用 / 何时不用
- 常见问题
- 下一步
1. 一句话了解 gRPC
gRPC是高性能、跨语言的RPC 框架:用Protocol Buffers在.proto里定义服务,用HTTP/2传输,由工具生成多语言客户端/服务端代码,让你像调本地函数一样调远程接口。
为什么用 gRPC?
- 性能好:二进制序列化 + HTTP/2 多路复用
- 强类型:.proto 即契约,编译期检查
- 自动代码生成:少写样板、多语言一致
- 支持流式:一元 / 客户端流 / 服务端流 / 双向流
2. 核心概念(4 步)
| 步骤 | 做什么 |
|---|---|
| 1. 定义服务 | 在.proto里写service、rpc、message |
| 2. 生成代码 | 用protoc+ gRPC 插件生成目标语言代码 |
| 3. 实现服务端 | 实现生成的 Service 接口,监听端口 |
| 4. 写客户端 | 建 Channel → 拿 Stub → 调用 RPC |
三个关键抽象:
- Channel:到服务端的逻辑连接(含解析、负载均衡、连接管理)
- Stub:客户端侧的类型安全接口,由 .proto 生成
- Service:服务端实现的业务逻辑,对应 .proto 里的 service
3. 四种 RPC 类型
| 类型 | 请求 | 响应 | 典型场景 |
|---|---|---|---|
| 一元 | 1 个 | 1 个 | 普通 API 调用 |
| 服务端流式 | 1 个 | 流 | 推送、大结果集 |
| 客户端流式 | 流 | 1 个 | 上传、批处理 |
| 双向流式 | 流 | 流 | 聊天、实时双向 |
4. 5 分钟上手(以 Python 为例)
4.1 安装
pipinstallgrpcio grpcio-tools其他语言安装:
| 语言 | 命令 |
|---|---|
| Go | go get google.golang.org/grpc |
| Node.js | npm install @grpc/grpc-js |
| Java | Maven:io.grpc:grpc-netty-shaded等 |
| C# | dotnet add package Grpc.Net.Client |
| Ruby | gem install grpc |
4.2 定义服务helloworld.proto
syntax = "proto3"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }Proto 语法速览:字段编号 1–15 编码更省;repeated表示列表;optional表示可选;常用类型有string、int32、int64、bool、bytes。服务里用stream表示流式,例如rpc StreamReply (Req) returns (stream Resp) {}。
4.3 生成代码
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto得到helloworld_pb2.py(消息)和helloworld_pb2_grpc.py(服务/存根)。
4.4 服务端(最简)
importgrpcfromconcurrentimportfuturesimporthelloworld_pb2importhelloworld_pb2_grpcclassGreeter(helloworld_pb2_grpc.GreeterServicer):defSayHello(self,request,context):returnhelloworld_pb2.HelloReply(message=f"Hello,{request.name}!")server=grpc.server(futures.ThreadPoolExecutor(max_workers=10))helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(),server)server.add_insecure_port("[::]:50051")server.start()server.wait_for_termination()4.5 客户端(最简)
importgrpcimporthelloworld_pb2importhelloworld_pb2_grpcwithgrpc.insecure_channel("localhost:50051")aschannel:stub=helloworld_pb2_grpc.GreeterStub(channel)reply=stub.SayHello(helloworld_pb2.HelloRequest(name="World"))print(reply.message)# Hello, World!4.6 运行
先起服务端,再在另一终端跑客户端。生产环境请使用 TLS 与正式凭据。
5. 错误处理与超时
错误与状态码:每次 RPC 返回一个Status(或语言等价物)。常见码:OK、CANCELLED、DEADLINE_EXCEEDED、UNAVAILABLE、UNAUTHENTICATED、PERMISSION_DENIED、NOT_FOUND、INVALID_ARGUMENT等。客户端应检查status.ok()或捕获异常后再使用响应。
超时(deadline):建议每次调用都设超时,避免挂死。例如 Python:response = stub.SayHello(request, timeout=10);或在 context/metadata 里设置 deadline。
取消:支持对进行中的 RPC 取消,客户端取消后服务端会收到取消信号,可做清理。
6. 元数据(Metadata)
元数据是键值对,随请求/响应传递,不写在 .proto 里。典型用途:认证 token、trace-id、请求来源、自定义头。
- 客户端发元数据:在调用前往 context 里塞入(如
metadata = [('key', 'value')],再传给 stub)。 - 服务端读/写:从
context.invocation_metadata()读请求元数据;通过context.send_initial_metadata()等回写响应元数据。
7. 同步 vs 异步
- 同步:调用阻塞直到拿到响应,写法简单,适合请求不多、逻辑顺序清晰的场景。
- 异步:非阻塞,通过回调或 Future/async 获取结果,适合高并发、多 RPC 并发。各语言都有异步 API(如 C++ 的 CompletionQueue/Callback、Python 的
grpc.aio)。
先掌握同步即可上手,有性能需求再上异步。
8. 安全速览
- 开发/内网:可用
insecure_channel/InsecureServerCredentials快速跑通。 - 生产:必须用TLS(
SslCredentials/SslServerCredentials),校验证书。需要双向认证时用mTLS(客户端也出示证书)。 - 应用层认证:在元数据里带 token,或使用CallCredentials(如 JWT、OAuth2),与 ChannelCredentials 组合使用。
9. 特性一览(记住这些就够了)
| 能力 | 说明 |
|---|---|
| 协议 | HTTP/2 + Protocol Buffers |
| 负载均衡 | 调用级,内置 round_robin、pick_first 等 |
| 安全 | TLS/mTLS、CallCredentials(如 JWT) |
| 超时与取消 | 每次调用可设 deadline,支持取消 |
| 元数据 | 键值对,随请求/响应传递 |
| 通道状态 | IDLE → CONNECTING → READY → TRANSIENT_FAILURE → SHUTDOWN |
10. 何时用 / 何时不用
适合 gRPC:微服务间通信、强契约与代码生成、流式或实时、多语言互操作。
可考虑 REST:面向浏览器的公开 API、简单 CRUD、强依赖 HTTP 缓存与生态。
11. 常见问题
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 端口已被占用 | 本机已有进程占用该端口 | 换端口或结束占用进程 |
| 连接被拒绝 / Connection refused | 服务端未起或地址/端口错误 | 先启动服务端,检查 host:port |
| 超时 / DEADLINE_EXCEEDED | 网络慢或服务端未响应 | 加大 timeout,检查服务端逻辑与网络 |
| 跨语言调用失败 | 协议版本或 .proto 不一致 | 保证两端用同一 .proto 定义并重新生成代码 |
提示:不同语言的服务端和客户端可以互连(如 Go 服务端 + Python 客户端),只要共用同一份 .proto 定义即可。
12. 下一步
- 官方:grpc.io — 各语言教程与 API 参考。
- 示例:grpc 仓库
examples/(如examples/python/helloworld、examples/cpp/helloworld、examples/node)。