gRPC 开发者快速入门
精简版快速入门,只保留核心概念与上手步骤。
目录
- [一句话了解 gRPC](#一句话了解 gRPC)
- [核心概念(4 步)](#核心概念(4 步))
- [四种 RPC 类型](#四种 RPC 类型)
- [5 分钟上手(以 Python 为例)](#5 分钟上手(以 Python 为例))
- 错误处理与超时
- 元数据(Metadata)
- [同步 vs 异步](#同步 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 安装
bash
pip install grpcio 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
protobuf
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 生成代码
bash
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
得到 helloworld_pb2.py(消息)和 helloworld_pb2_grpc.py(服务/存根)。
4.4 服务端(最简)
python
import grpc
from concurrent import futures
import helloworld_pb2
import helloworld_pb2_grpc
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_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 客户端(最简)
python
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
with grpc.insecure_channel("localhost:50051") as channel:
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)。