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 | 多条 | 多条 | 聊天、协同编辑 |
选型方向:数据是单向还是双向?是一批还是一条?记住两个判断维度,模式就很容易选。
嗯,我们来看一张流程图,帮大家更直观地理解这四种模式的交互差异。
4.6 如何选?我的经验法
你想想看,如果连你自己都说不清选哪个,说明你对场景理解还不够深。我个人习惯是用两个问题做判断:
- 数据是从哪到哪? 是客户端单个还是批量?服务端要返回一批还是一处?
- 实时要求高吗? 高 -> 考虑流式。不高 -> Unary。
最后留一句:模式选对了,后面调优才有的放矢。模式选错了,后面怎么改都别扭。