【一文读懂GRPC】GRPC完全教程指南
目录
前言
gRPC 的名称来源于 "Google Remote Procedure Call",最初由 Google 在 2015 年开源,现已成为云原生计算基金会(CNCF)的孵化项目,被广泛应用于 Kubernetes、Envoy 等知名项目中。gRPC 接口简介
gRPC 是一种高性能、开源的远程过程调用(RPC)框架,由 Google 开发,旨在简化分布式系统中服务之间的通信。它基于 HTTP/2 协议,并使用 Protocol Buffers 作为接口定义语言(IDL)和消息序列化格式,提供了高效、强类型、跨语言的通信能力。
一、核心概念与工作原理
1-1、什么是 RPC
RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,允许程序调用位于另一台计算机上的子程序,而无需显式处理底层网络通信细节。对于开发者而言,调用远程服务就像调用本地函数一样简单。
1-2、gRPC 的工作流程
gRPC 允许客户端像调用本地方法一样调用远程服务。服务通过 .proto 文件定义,其中包含服务接口、方法、参数和返回类型。通过 gRPC 的工具链,可以自动生成客户端存根(stub)和服务器骨架(skeleton)代码。
通信过程包括以下步骤:
- 客户端调用:客户端调用本地存根方法,就像调用普通函数一样
- 序列化:请求数据被序列化为 Protocol Buffers 二进制格式
- 传输:数据通过 HTTP/2 传输到服务器
- 服务端处理:服务器反序列化数据,调用对应的服务逻辑
- 响应返回:服务器返回序列化后的响应数据,客户端接收并反序列化
如下图所示:(今天的图是中英文双语版本,花钱了都得贴上来!)

二、gRPC 的主要特性
2-1、高性能
- 基于 HTTP/2 协议,支持多路复用、头部压缩和服务器推送
- 单一 TCP 连接上可并发处理多个请求/响应,显著降低延迟
- 二进制分帧层提供更高效的数据传输
2-2、Protocol Buffers
- Google 开发的结构化数据序列化格式
- 比 JSON 或 XML 更紧凑(通常小 3-10 倍),解析速度更快(快 20-100 倍)
- 强类型定义,编译时即可发现类型错误
- 支持向后和向前兼容的演化
2-3、强类型与代码生成
- 通过
.proto文件定义服务契约 - 自动生成客户端和服务端代码(支持 10+ 种语言)
- 编译时类型检查,减少运行时错误
2-4、流式通信模式
gRPC 支持四种通信模式,满足不同场景需求:
| 模式 | 描述 | 适用场景 |
|---|---|---|
| Unary RPC | 客户端发送单个请求,服务端返回单个响应 | 简单的请求-响应场景 |
| Server Streaming | 客户端发送单个请求,服务端返回多个响应 | 数据推送、实时通知 |
| Client Streaming | 客户端发送多个请求,服务端返回单个响应 | 文件上传、批量处理 |
| Bidirectional Streaming | 客户端和服务端都可以独立发送多个消息 | 实时聊天、在线游戏 |
2-5、自动代码生成
- 使用
protoc编译器自动生成代码 - 简化开发流程,减少手动编码工作量
- 保持多语言之间接口的一致性
三、gRPC 的优势与适用场景
gRPC 在性能、类型安全和多语言支持方面具有显著优势,特别适用于以下场景:
3-1、微服务架构
- 服务间高效通信:低延迟、高吞吐量的内部服务调用
- 服务发现集成:与 Consul、etcd、Kubernetes 等服务发现工具无缝集成
- 负载均衡:支持客户端和服务端负载均衡
3-2、移动客户端与浏览器
- 低延迟:更小的数据包体积,更快的序列化速度
- 低带宽消耗:二进制格式比 JSON 更紧凑
- gRPC-Web:支持浏览器客户端通过 HTTP/1.1 调用 gRPC 服务
3-3、实时应用
- 在线游戏:低延迟的双向流通信
- 实时数据分析:持续的数据流推送
- IoT 设备通信:高效的资源利用,适合受限设备
3-4、跨语言系统
- 多语言团队协作:不同技术栈的服务可以无缝集成
- 遗留系统现代化:逐步迁移,保持接口兼容
GRPC的优势与适用场景如下所示:
四、gRPC vs REST 详细对比
| 特性 | gRPC | REST |
|---|---|---|
| 协议 | HTTP/2 | HTTP/1.1 或 HTTP/2 |
| 数据格式 | Protocol Buffers(二进制) | JSON/XML(文本) |
| 性能 | 高(二进制,体积小,解析快) | 中(文本格式,体积大) |
| 流式支持 | 原生支持四种流模式 | 需额外实现(如 WebSocket) |
| 类型安全 | 强类型,编译时检查 | 弱类型,运行时检查 |
| 代码生成 | 自动生成客户端/服务端代码 | 需手动编写或使用第三方工具 |
| 浏览器支持 | 需 gRPC-Web 代理 | 原生支持 |
| 调试难度 | 较难(二进制格式) | 简单(人类可读) |
| 缓存 | 需额外配置 | HTTP 缓存机制成熟 |
4-1、选择建议
使用 gRPC 的场景:
- 内部微服务通信
- 需要高性能、低延迟的场景
- 多语言环境下的服务集成
- 实时流数据处理
使用 REST 的场景:
- 对外公开的 API
- 需要浏览器直接访问的场景
- 需要利用 HTTP 缓存机制
- 调试和测试便利性优先
五、示例:定义与实现
5-0、架构图&依赖安装
整体架构图:
┌─────────────────────────────────────────────────────────────────┐
│ gRPC 工作流程 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────┐ ┌─────────────┐
│ 客户端 │ ◄────────────────► │ 服务端 │
│ (client.py) │ HTTP/2 网络 │ (service.py) │
└──────┬──────┘ └──────┬──────┘
│ │
│ 1. 调用存根方法 │
│ stub.SayHello(request) │
│ │
│ 2. 序列化 (Protobuf) │
│ HelloRequest → 二进制数据 │
│ │
│ 3. HTTP/2 传输 │
│ 发送二进制数据 ─────────────────►│
│ │
│ 4. 反序列化
│ 二进制 → HelloRequest
│ │
│ 5. 执行业务逻辑
│ GreeterService.SayHello()
│ │
│ 6. 序列化响应
│ HelloReply → 二进制
│ │
│ 7. 反序列化响应 ◄─────────────────│
│ 二进制 → HelloReply │
│ │
│ 8. 返回结果 │
│ response.message │
依赖安装:
pip install grpcio grpcio-tools
我的代码文件目录如下所示:
D:\pycharmProject\jf_inner_skills\Local\Experiment\GRPC\
├── client.py # 客户端代码
├── grpc.md # 文档
├── grpc.proto # proto 文件
└── service.py # 服务端代码
5-1、定义服务(grpc.proto 文件)
以下是一个简单的 gRPC 服务定义示例:这相当于约定接口,客户端和服务端都同意 “有一个叫 SayHello 的方法,接收 HelloRequest,返回 HelloReply”。
syntax = "proto3";
package example;
// 定义服务
service Greeter {
// 一元 RPC
rpc SayHello (HelloRequest) returns (HelloReply);
// 服务端流式 RPC
rpc SayHelloStream (HelloRequest) returns (stream HelloReply);
}
// 请求消息
message HelloRequest {
string name = 1;
int32 age = 2;
repeated string hobbies = 3; // 重复字段(数组)
}
// 响应消息
message HelloReply {
string message = 1;
int64 timestamp = 2;
}
生成python代码:
cd D:\pycharmProject\jf_inner_skills\Local\Experiment\GRPC
python -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. grpc.proto
执行后会生成:
- grpc_pb2.py
- grpc_pb2_grpc.py
这会根据 proto 文件自动生成:
- grpc_pb2.py - 消息类(HelloRequest, HelloReply)
- grpc_pb2_grpc.py - 服务类(GreeterServicer, GreeterStub)
为什么需要生成?
- 把 proto 定义转换成 Python 代码
- 包含序列化/反序列化的逻辑
- 包含网络通信的底层代码
5-2、服务端实现(Python service.py)
通过 protoc 工具生成代码后,开发者可以实现服务端逻辑:
- 创建一个 gRPC 服务器,监听 50051 端口
- 注册 GreeterService 实现类
- 等待客户端请求
- 收到请求后,自动反序列化,调用 SayHello 方法
- 把返回值序列化,发回客户端
from concurrent import futures
import grpc
import time
# 这里导入的是刚才生成的两个文件
import grpc_pb2
import grpc_pb2_grpc
class GreeterService(grpc_pb2_grpc.GreeterServicer):
"""实现 Greeter 服务"""
def SayHello(self, request, context):
"""处理一元 RPC 请求"""
# 获取请求参数
name = request.name
age = request.age
hobbies = request.hobbies
# 构建响应
message = f"Hello, {name}! You are {age} years old."
if hobbies:
message += f" Your hobbies: {', '.join(hobbies)}"
return grpc_pb2.HelloReply(
message=message,
timestamp=int(time.time())
)
def SayHelloStream(self, request, context):
"""处理服务端流式 RPC 请求"""
name = request.name
for i in range(5):
yield grpc_pb2.HelloReply(
message=f"Hello {name}, message {i + 1}",
timestamp=int(time.time())
)
time.sleep(1)
def serve():
"""启动 gRPC 服务器"""
# 创建线程池,最大 10 个工作线程
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
# 注册服务
grpc_pb2_grpc.add_GreeterServicer_to_server(GreeterService(), server)
# 绑定端口
server.add_insecure_port('[::]:50051')
# 启动服务
server.start()
print("gRPC server started on port 50051")
# 等待终止
server.wait_for_termination()
if __name__ == '__main__':
serve()
5-3、客户端实现(Python client.py)
客户端可以通过生成的存根调用服务:
- 建立到服务端的连接(channel)
- 创建存根(Stub) - 相当于远程服务的本地代理
- 调用 stub.SayHello(),就像调用本地函数一样
- gRPC 自动完成:序列化请求 → 发送 → 等待响应 → 反序列化响应
- 返回 response 对象
import grpc
import greeter_pb2
import greeter_pb2_grpc
def run_unary():
"""一元 RPC 调用示例"""
# 创建不安全的通道
channel = grpc.insecure_channel('localhost:50051')
# 创建客户端存根
stub = greeter_pb2_grpc.GreeterStub(channel)
# 构建请求
request = greeter_pb2.HelloRequest(
name="World",
age=25,
hobbies=["coding", "reading"]
)
# 调用远程方法
try:
response = stub.SayHello(request)
print(f"Received: {response.message}")
print(f"Timestamp: {response.timestamp}")
except grpc.RpcError as e:
print(f"RPC failed: {e.code()}: {e.details()}")
def run_streaming():
"""流式 RPC 调用示例"""
channel = grpc.insecure_channel('localhost:50051')
stub = greeter_pb2_grpc.GreeterStub(channel)
request = greeter_pb2.HelloRequest(name="StreamUser")
# 处理流式响应
responses = stub.SayHelloStream(request)
for response in responses:
print(f"Stream received: {response.message}")
if __name__ == '__main__':
run_unary()
# run_streaming()
启动服务器端以及客户端:
cd D:\pycharmProject\jf_inner_skills\Local\Experiment\GRPC
python service.py
python client.py
启动后如下图所示:

5-4、核心概念解释

5-5、流程总结
写 proto 文件 ──► 生成代码 ──► 服务端实现业务逻辑 ──► 客户端调用存根
│ │ │ │
▼ ▼ ▼ ▼
定义接口 自动生成 启动服务等待请求 像调本地函数一样
服务和消息 序列化代码 自动反序列化/序列化 自动完成网络通信
六、高级特性
6-1、拦截器(Interceptors)
拦截器允许在请求处理前后执行自定义逻辑,如日志记录、认证、监控等:
class LoggingInterceptor(grpc.ServerInterceptor):
def intercept_service(self, continuation, handler_call_details):
print(f"Received call: {handler_call_details.method}")
return continuation(handler_call_details)
6-2、元数据(Metadata)
通过元数据传递额外的上下文信息,如认证令牌、请求 ID 等:
# 客户端发送元数据
metadata = [('authorization', 'Bearer token123')]
response = stub.SayHello(request, metadata=metadata)
# 服务端读取元数据
metadata = dict(context.invocation_metadata())
token = metadata.get('authorization', '')
6-3、截止时间(Deadline)
设置请求超时时间,防止长时间等待:
# 设置 5 秒超时
try:
response = stub.SayHello(request, timeout=5)
except grpc.RpcError as e:
if e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
print("Request timed out")
6-4、错误处理
gRPC 使用状态码表示错误类型:
| 状态码 | 描述 |
|---|---|
OK |
成功 |
CANCELLED |
操作被取消 |
UNKNOWN |
未知错误 |
INVALID_ARGUMENT |
参数无效 |
DEADLINE_EXCEEDED |
超时 |
NOT_FOUND |
资源未找到 |
ALREADY_EXISTS |
资源已存在 |
PERMISSION_DENIED |
权限不足 |
UNAUTHENTICATED |
未认证 |
UNAVAILABLE |
服务不可用 |
七、注意事项与最佳实践
7-1、版本兼容性
- Protocol Buffers 提供良好的前后向兼容性
- 字段编号一旦分配不可更改,只能废弃
- 字段类型更改需谨慎,可能导致兼容性问题
- 新增字段使用
optional或设置默认值
7-2、安全性
- TLS/SSL:生产环境必须使用加密传输
credentials = grpc.ssl_channel_credentials() channel = grpc.secure_channel('server.com:50051', credentials) - 认证机制:支持 OAuth2、JWT、自定义令牌等
- 拦截器认证:在拦截器中统一处理认证逻辑
7-3、性能优化
- 连接池:复用 gRPC 通道,避免频繁创建
- 流控:合理设置窗口大小和缓冲区
- 压缩:启用消息压缩减少传输体积
channel = grpc.insecure_channel( 'localhost:50051', options=[('grpc.default_compression_algorithm', 2)] )
7-4、调试工具
- grpcurl:命令行工具,类似 curl,用于测试 gRPC 服务
grpcurl -plaintext localhost:50051 list grpcurl -plaintext -d '{"name":"World"}' localhost:50051 example.Greeter/SayHello - BloomRPC:图形化 gRPC 客户端工具
- Wireshark:支持 HTTP/2 和 protobuf 解析
- gRPC 反射:启用反射服务供调试工具发现服务定义
7-5、生产环境建议
- 使用服务网格(如 Istio、Linkerd)管理服务间通信
- 实现健康检查和优雅关闭
- 配置适当的超时和重试策略
- 监控关键指标:延迟、错误率、吞吐量
八、总结
gRPC 是现代分布式系统中高效、可靠的通信解决方案,特别适合:
- 高性能要求的微服务架构
- 多语言环境下的服务集成
- 实时数据流处理场景
- 移动和 IoT 设备通信
通过 Protocol Buffers 提供的强类型契约、HTTP/2 的高性能传输,以及丰富的流式通信模式,gRPC 已成为云原生时代服务间通信的首选方案之一。
总结
还得是Nanobanana。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)