更新时间:2026-03-27 | 阅读时间:约 15 分钟
gRPC(gRPC Remote Procedure Calls)是 Google 于 2015 年开源的高性能远程过程调用框架。它基于 HTTP/2 协议,使用 Protocol Buffers 作为接口描述语言和数据序列化格式,支持多种编程语言。
| 特性 | gRPC | REST |
|---|---|---|
| 协议 | HTTP/2 | HTTP/1.1 或 HTTP/2 |
| 数据格式 | Protocol Buffers(二进制) | JSON/XML(文本) |
| 性能 | 高(二进制序列化) | 中(文本解析开销) |
| 类型系统 | 强类型(.proto 定义) | 弱类型(需额外文档) |
| 流式支持 | 原生支持双向流 | 需要额外实现 |
| 浏览器支持 | 需要 gRPC-Web 代理 | 原生支持 |
Protocol Buffers(简称 Protobuf)是 gRPC 的接口描述语言和数据序列化格式。通过 .proto 文件定义消息结构和服务接口。
// 定义请求消息
message UserRequest {
int32 user_id = 1; // 字段编号,用于二进制编码
string username = 2;
}
// 定义响应消息
message UserResponse {
int32 user_id = 1;
string username = 2;
string email = 3;
bool is_active = 4;
}
| 类型 | 说明 | 示例 |
|---|---|---|
| 标量类型 | 基础数据类型 | int32, int64, uint32, uint64, float, double, bool, string, bytes |
| 枚举类型 | 自定义枚举 | enum Status { UNKNOWN = 0; SUCCESS = 1; ERROR = 2; } |
| 重复字段 | 数组/列表 | repeated string tags = 5; |
| Map 字段 | 键值对 | map<string, int32> scores = 6; |
| 嵌套消息 | 消息中包含消息 | Address address = 7; |
// 定义服务接口
service UserService {
// 一元 RPC:客户端发送一个请求,服务器返回一个响应
rpc GetUser(UserRequest) returns (UserResponse);
// 服务器流:客户端发送一个请求,服务器返回流式响应
rpc ListUsers(ListUsersRequest) returns (stream UserResponse);
// 客户端流:客户端发送流式请求,服务器返回一个响应
rpc CreateUser(stream UserRequest) returns (UserResponse);
// 双向流:客户端和服务器都使用流式通信
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
# macOS
brew install protobuf
# Linux (Ubuntu/Debian)
sudo apt-get install protobuf-compiler
# 验证安装
protoc --version
# Python
pip install grpcio grpcio-tools
# Node.js
npm install @grpc/grpc-js @grpc/proto-loader
# Go
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
// user.proto
syntax = "proto3";
package user;
// 请求消息
message GetUserRequest {
int32 user_id = 1;
}
// 响应消息
message GetUserResponse {
int32 user_id = 1;
string username = 2;
string email = 3;
}
// 服务定义
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
}
# Python
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. user.proto
# Node.js (使用 ts-proto 或 protobufjs)
npx protoc --ts_out=. --proto_path=. user.proto
# Go
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
user.proto
import grpc
from concurrent import futures
import user_pb2
import user_pb2_grpc
class UserServiceServicer(user_pb2_grpc.UserServiceServicer):
def GetUser(self, request, context):
# 模拟从数据库获取用户
user_data = {
1: {"username": "alice", "email": "alice@example.com"},
2: {"username": "bob", "email": "bob@example.com"}
}
user_id = request.user_id
if user_id in user_data:
return user_pb2.GetUserResponse(
user_id=user_id,
username=user_data[user_id]["username"],
email=user_data[user_id]["email"]
)
else:
context.set_code(grpc.StatusCode.NOT_FOUND)
context.set_details("User not found")
return user_pb2.GetUserResponse()
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
user_pb2_grpc.add_UserServiceServicer_to_server(
UserServiceServicer(), server
)
server.add_insecure_port('[::]:50051')
server.start()
print("Server started on port 50051")
server.wait_for_termination()
if __name__ == '__main__':
serve()
import grpc
import user_pb2
import user_pb2_grpc
def run():
# 连接到 gRPC 服务器
channel = grpc.insecure_channel('localhost:50051')
stub = user_pb2_grpc.UserServiceStub(channel)
# 调用 RPC 方法
request = user_pb2.GetUserRequest(user_id=1)
response = stub.GetUser(request)
print(f"User ID: {response.user_id}")
print(f"Username: {response.username}")
print(f"Email: {response.email}")
if __name__ == '__main__':
run()
最简单的调用模式,客户端发送一个请求,服务器返回一个响应。
// .proto 定义
rpc GetUser(GetUserRequest) returns (GetUserResponse);
// 客户端调用
response = stub.GetUser(request)
客户端发送一个请求,服务器返回一系列响应。
// .proto 定义
rpc ListUsers(ListUsersRequest) returns (stream UserResponse);
// 服务端实现
def ListUsers(self, request, context):
for user in get_all_users():
yield user_pb2.UserResponse(**user)
// 客户端调用
for response in stub.ListUsers(request):
print(response)
客户端发送一系列请求,服务器返回一个响应。
// .proto 定义
rpc CreateUser(stream UserRequest) returns (UserResponse);
// 客户端调用
def generate_requests():
for user_data in users:
yield user_pb2.UserRequest(**user_data)
response = stub.CreateUser(generate_requests())
客户端和服务器都使用流式通信,双方可以独立读写。
// .proto 定义
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
// 客户端实现
def generate_messages():
for msg in messages:
yield chat_pb2.ChatMessage(text=msg)
response = stub.Chat(generate_messages())
for resp in response:
print(resp.text)
# 使用 SSL/TLS 加密
credentials = grpc.ssl_channel_credentials()
channel = grpc.secure_channel('localhost:50051', credentials)
# 添加认证元数据
metadata = [('authorization', 'Bearer token123')]
response = stub.GetUser(request, metadata=metadata)
from grpc import StatusCode
try:
response = stub.GetUser(request)
except grpc.RpcError as e:
if e.code() == StatusCode.NOT_FOUND:
print("User not found")
elif e.code() == StatusCode.UNAVAILABLE:
print("Server unavailable")
else:
print(f"Error: {e.details()}")
# 设置超时
response = stub.GetUser(request, timeout=5.0)
# 使用重试配置
channel = grpc.insecure_channel(
'localhost:50051',
options=[
('grpc.enable_retries', 1),
('grpc.max_receive_message_length', 4 * 1024 * 1024)
]
)
gRPC 是微服务架构中服务间通信的理想选择,具有高性能、强类型、多语言支持等优势。
使用双向流式 RPC 实现实时聊天、实时数据推送、实时协作编辑等场景。
gRPC 的二进制序列化减少了数据传输量,适合移动网络环境。
gRPC 的低开销和高效性能适合资源受限的 IoT 设备。
gRPC 是一个强大的 RPC 框架,特别适合微服务架构和高性能通信场景。通过 Protocol Buffers 定义强类型接口,支持多种调用模式,并提供丰富的生态系统支持。掌握 gRPC 将帮助你构建更高效、更可靠的分布式系统。