4. gRPC 四种通信模式:对比与选型

聊到 gRPC 的通信模式,很多朋友第一反应就是“四种模式,背下来就行了”。说实话,我不这么看。你硬背下来,出门换个项目一样懵。我个人习惯是把模式理解成“不同的对话方式”,场景对了,模式自然就选对了。

好,我们一个个来过。

4.1 一元 RPC(Unary RPC)

说白了就是“一问一答”。 客户端给你发一个请求,你处理完再给一个响应。简单直接,跟传统 HTTP 接口一模一样。

我参与过一个用户登录服务,用的就是 Unary。客户端传个用户名密码,我后端校验完了返回 。没什么复杂的地方,一个 request,一个 response,搞定。

  • 特点:请求-响应模式,一对一。
  • 适用场景:简单的 CRUD、登录、查询单个资源。
  • 注意:别把一个批量要传 10 万条数据的接口也塞进 Unary,会出事的。
核心判断:客户端发一个请求,只需要一个响应,够用。别再想花样。
我的习惯:写 Protobuf 时,如果 rpc 后面的参数和返回值都不是 stream,那就是 Unary RPC。代码里一眼就能认出来。

4.2 服务端流式 RPC(Server Streaming RPC)

还是客户端发一个请求。但服务端呢,可以给你吐一堆数据回来。像什么实时汇率、股票行情、日志推送,都是它的主场。

我记得有一次改造推送系统。原本是客户端定时轮询,每次拉一堆订单数据回来,压力大得不行。改成 Server Streaming 后,服务端有数据直接推,客户端性能直接起飞。

  • 特点:一个请求,多条响应流。
  • 适用场景:监控数据推送、大文件分片下载、实时通知。
  • 避坑指南:服务端发完了要记得调 onCompleted(),不然客户端就永远等下去了。我曾经因为忘写这行,被运维喊去查了半小时日志。
警告:服务端流式模式下,客户端会一直保持连接接收数据。如果流量不大,别让客户端挂太久。资源回收要谨慎。

4.3 客户端流式 RPC(Client Streaming RPC)

反过来,客户端可以像拧水龙头一样,一点一点地把数据发过去。服务端等客户端说“够了”,再给你一个响应。

你想想看,一个上传文件或者批量提交数据的场景。客户端一条一条发,服务端边收边处理,最后统一给个结果。这不就是 Client Streaming 的经典用法吗?

  • 特点:多条请求,一个响应。
  • 适用场景:批量数据导入、实时日志收集、文件上传(分片)。
  • 注意:客户端一定要记得调 onComplete(),不然服务端永远等不到结束。
我的建议:如果请求之间没有顺序依赖,可以考虑 Client Streaming + 服务端合并处理,能省掉很多连接开销。

4.4 双向流式 RPC(Bidirectional Streaming RPC)

这个模式我最喜欢。客户端和服务端可以同时说话,互不干扰。就像两个人打字聊天,你发你的,我回我的。

我在做一个聊天系统时,底层用的就是双向流。客户端发消息,服务端收;服务端有推送,客户端也能收到。两边都畅通,体验就好。

  • 特点:双向独立流,全双工。
  • 适用场景:实时聊天、游戏对战、协同编辑、在线客服。
  • 难度:代码结构比前面复杂,但用熟了其实就是一个循环读取的套路。
注意:双向流不是“同步对话”。两边的流是独立的,不要以为一定能对齐。我见过有人写双向流时,硬等服务端回一条才发下一条,把全双工用成了半双工,白白浪费设计优势。

4.5 模式对比速览

模式 请求方向 响应方向 典型应用
Unary 1 条 1 条 查询用户、登录
Server Streaming 1 条 多条 日志推送、行情
Client Streaming 多条 1 条 批量导入、上传
Bidirectional Streaming 多条 多条 聊天、协同编辑
选型方向:数据是单向还是双向?是一批还是一条?记住两个判断维度,模式就很容易选。

嗯,我们来看一张流程图,帮大家更直观地理解这四种模式的交互差异。

gRPC 四种通信模式对比 Unary 1 请求 → 1 响应 Server Streaming 1 请求 → 多条响应 Client Streaming 多条请求 → 1 响应 双向流 多条请求/响应 客户端 → 服务端 服务端 → 客户端 客户端 → 服务端 服务端 → 客户端(多条) 客户端(多条) → 服务端 服务端 → 客户端 客户端 ↔ 服务端 双向独立流 登录 简单查询 健康检查 日志推送 实时行情 大文件分片 批量导入 日志收集 传感器数据 实时聊天 游戏对战 协同编辑 选择哪种模式? 评估数据量 + 方向需求。单向且数据量大 = Streaming;双向且数据量大 = 双向流;其他情况 Unary 即可

4.6 如何选?我的经验法

你想想看,如果连你自己都说不清选哪个,说明你对场景理解还不够深。我个人习惯是用两个问题做判断:

  1. 数据是从哪到哪? 是客户端单个还是批量?服务端要返回一批还是一处?
  2. 实时要求高吗? 高 -> 考虑流式。不高 -> Unary。

最后留一句:模式选对了,后面调优才有的放矢。模式选错了,后面怎么改都别扭。