中 进阶
gRPC流式通信模式#
一句话答案#
gRPC 基于 HTTP/2 的 stream 机制提供四种通信模式:Unary(一问一答)、Server Streaming(服务端推流)、Client Streaming(客户端上传流)、Bidirectional Streaming(双向流),解决了 REST 无法优雅处理的实时推送、大数据分批传输和双向通信场景。
核心要点
四种模式对比#
| 模式 | 请求 | 响应 | 典型场景 |
|---|---|---|---|
| Unary | 1 | 1 | CRUD 操作、普通查询 |
| Server Streaming | 1 | N | 日志推送、实时行情、分页拉取 |
| Client Streaming | N | 1 | 文件上传、批量数据写入、IoT 采集 |
| Bidirectional | N | N | 聊天、协同编辑、实时游戏 |
Server Streaming 示例#
// Proto 定义
rpc ListOrders(ListRequest) returns (stream OrderResponse);
// 服务端实现
@Override
public void listOrders(ListRequest req, StreamObserver<OrderResponse> responseObserver) {
List<Order> orders = orderDao.queryByUser(req.getUserId());
for (Order order : orders) {
responseObserver.onNext(toProto(order)); // 逐条推送
}
responseObserver.onCompleted(); // 结束流
}
// 客户端消费
stub.listOrders(request, new StreamObserver<OrderResponse>() {
@Override public void onNext(OrderResponse resp) { /* 处理每条 */ }
@Override public void onCompleted() { /* 流结束 */ }
@Override public void onError(Throwable t) { /* 异常处理 */ }
});javaBidirectional Streaming 示例#
// Proto 定义
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
// 服务端
@Override
public StreamObserver<ChatMessage> chat(StreamObserver<ChatMessage> responseObserver) {
return new StreamObserver<ChatMessage>() {
@Override public void onNext(ChatMessage msg) {
// 收到客户端消息,处理后推回
responseObserver.onNext(process(msg));
}
@Override public void onCompleted() { responseObserver.onCompleted(); }
@Override public void onError(Throwable t) { /* handle */ }
};
}java流控(Flow Control)#
HTTP/2 内置流控机制:
1. 连接级窗口:控制整个连接的总数据量
2. Stream 级窗口:控制单个 stream 的数据量
3. 接收方通过 WINDOW_UPDATE 帧通知发送方可以继续发
gRPC 层面:
- 客户端可以调用 request(n) 指定拉取数量(Reactive 风格)
- 服务端检测 isReady() 避免无限制推送导致 OOMplaintextStreaming vs WebSocket vs SSE#
| 维度 | gRPC Streaming | WebSocket | SSE |
|---|---|---|---|
| 协议 | HTTP/2 | 升级为 WS 协议 | HTTP/1.1 |
| 方向 | 四种模式 | 全双工 | 服务端→客户端 |
| 序列化 | Protobuf(强类型) | 自定义 | 文本 |
| 浏览器支持 | 需 gRPC-Web 代理 | 原生 | 原生 |
| 适用 | 服务间通信 | 前端实时 | 前端通知 |
面试回答(2分钟版)
gRPC 利用 HTTP/2 的 stream 特性支持四种通信模式。Unary 就是普通的一问一答,覆盖大部分 CRUD 场景。Server Streaming 适合服务端向客户端推送大量数据,比如日志流、实时行情,客户端发一个请求,服务端通过 onNext 逐条推送、onCompleted 结束。Client Streaming 适合批量上传场景,客户端连续发多条数据,服务端最后汇总返回一个结果。Bidirectional Streaming 是双向流,双方都可以随时发送,适合聊天和协同编辑。底层靠 HTTP/2 的多路复用和流控窗口保证不会 OOM:接收方通过 WINDOW_UPDATE 帧通知发送方能继续发多少。和 WebSocket 对比,gRPC Streaming 的优势是强类型(Protobuf IDL 约束)、原生流控、适合服务间通信;WebSocket 优势是浏览器原生支持。
追问与易错
追问方向:
- “Streaming 怎么做流控?”→ HTTP/2 窗口机制 + gRPC 的 isReady()/request(n)
- “Bidirectional 和 WebSocket 什么区别?”→ 协议不同、gRPC 强类型、需代理才能给浏览器用
- “流中间出错怎么办?”→ onError 回调 + Status Code + 客户端可以 retry
- “能做到消息有序吗?”→ 单个 stream 内有序,多个 stream 无序
易错点:
- ❌ “Streaming 会占满一个 TCP 连接”——HTTP/2 多路复用,一个连接可以并行多个 stream
- ❌ “Server Streaming 就是长轮询”——本质是服务端主动推送,不是客户端反复请求
- ❌ “双向流需要两个连接”——一个 HTTP/2 连接内双向 stream