gRPC 全面解析与实战 —— 从原理到同步/异步开发全攻略
目录
- 1. gRPC 基本原理
- 1.1 什么是 RPC 与 gRPC
- 1.2 gRPC 的核心特性
- 1.3 适用场景
- 2. 数据封装与传输
- 2.1 JSON vs Protobuf
- 2.2 HTTP/2 的加持
- 3. gRPC 四种通信模式
- 3.1 一元 RPC(Unary RPC)
- 3.2 服务端流(Server Streaming)
- 3.3 客户端流(Client Streaming)
- 3.4 双向流(Bidirectional Streaming)
- 4. 同步与异步调用
- 4.1 同步调用
- 4.2 异步调用
- 5. C++ gRPC 实战示例
- 5.1 定义 proto 文件
- 5.2 服务端实现
- 5.3 客户端调用
- 6. 异步模式流程图
- 7. 流式 RPC 实战
- 8. 总结
1. gRPC 基本原理
1.1 什么是 RPC 与 gRPC
-
RPC(Remote Procedure Call):让我们像调用本地方法一样调用远程服务。
-
gRPC:
- Google 开发的开源、高性能、跨语言 RPC 框架
- 基于 HTTP/2 协议
- 使用 Protocol Buffers(Protobuf) 作为序列化方案
简单理解:
你写了一个 HelloWorld()
函数,可以在另一台服务器上直接调用它,而不必关心底层 TCP 传输、序列化、网络延迟等细节,这就是 gRPC 带来的便利。
1.2 gRPC 的核心特性
-
跨语言:Java 写的服务,Go、Python、C++ 都能直接调用
-
高性能:基于 HTTP/2,多路复用,头部压缩,低延迟
-
同步与异步调用:支持阻塞和非阻塞模式
-
多种通信模式:
- 一元调用(Unary)
- 服务端流(Server Streaming)
- 客户端流(Client Streaming)
- 双向流(Bidirectional Streaming)
-
可扩展设计:可插拔的负载均衡、服务发现、监控、认证机制
1.3 适用场景
- 微服务间高效通信
- 客户端与云服务的数据交互
- 跨语言、大规模分布式系统
- 需要低延迟、高吞吐的 API 服务
2. 数据封装与传输
2.1 JSON vs Protobuf
特性 | JSON | Protobuf |
---|---|---|
可读性 | 高(面向人类) | 低(面向机器) |
体积 | 较大 | 较小(压缩率高) |
性能 | 解析慢 | 解析快 |
类型安全 | 弱 | 强(IDL 定义) |
跨语言 | 支持 | 支持 |
gRPC 选择 Protobuf,因为它能用一份 .proto
文件定义接口和数据结构,并为多语言生成对应代码。
示例:
service Test {rpc HowRpcDefine (Request) returns (Response);
}message Request {int64 user_id = 1;string name = 2;
}message Response {repeated int64 ids = 1;
}
2.2 HTTP/2 的加持
HTTP/2 解决了 HTTP/1.1 的串行阻塞问题:
- 流(Stream):每个请求都有唯一 ID,可并发处理
- 帧(Frame):数据被拆分成帧,乱序发送,接收端按 ID 重组
- 多路复用:一个 TCP 连接可同时承载多个请求
- 二进制传输:减少头部开销
这让 gRPC 在高并发场景下表现极佳。
3. gRPC 四种通信模式
3.1 一元 RPC(Unary RPC)
一次请求,一次响应。
场景:获取用户信息、提交表单。
3.2 服务端流(Server Streaming)
客户端发一次请求,服务端返回一个数据流。
场景:实时日志、视频流。
3.3 客户端流(Client Streaming)
客户端连续发送多个请求,服务端最后一次性响应。
场景:批量数据上传。
3.4 双向流(Bidirectional Streaming)
两端都可以持续收发数据,顺序不固定。
场景:在线聊天、实时协作。
4. 同步与异步调用
4.1 同步调用
- 客户端调用 RPC 后阻塞等待结果
- 简单直观,适合低并发、对实时性要求不高的场景
4.2 异步调用
- 基于 CompletionQueue 管理异步事件
- 使用 Tag 关联请求和响应
- 可以同时处理多个请求,提高并发能力
5. C++ gRPC 实战示例
5.1 定义 proto 文件
syntax = "proto3";service Greeter {rpc SayHello (HelloRequest) returns (HelloReply) {}
}message HelloRequest {string name = 1;
}message HelloReply {string message = 1;
}
5.2 服务端实现
class GreeterServiceImpl final : public Greeter::Service {Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override {reply->set_message("Hello " + request->name());return Status::OK;}
};
5.3 客户端调用
GreeterClient greeter(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
std::string reply = greeter.SayHello("world");
std::cout << reply << std::endl;
6. 异步模式流程图
[客户端] --调用--> [Stub] --请求--> [Channel]^ || v[响应]<--CompletionQueue<--[服务端处理逻辑]
7. 流式 RPC 实战
以双向流为例:
auto stream = stub_->RouteChat(&context);
std::thread writer([stream]() {stream->Write(note1);stream->Write(note2);stream->WritesDone();
});
RouteNote server_note;
while (stream->Read(&server_note)) {std::cout << "Received: " << server_note.message() << std::endl;
}
writer.join();
Status status = stream->Finish();
8. 总结
gRPC 通过 HTTP/2 + Protobuf,在分布式通信中兼顾了高性能与跨语言特性。
参考:
- 0voice · GitHub