Skip to main content

gRPC 四种 RPC 通信模式

这四种流式通信模式,本质上是由 客户端发起的请求流 和 服务端返回的响应流 组合而成的。核心区别在于发送或接收消息的次数。

我用一张表帮你快速理清,再逐一深入讲解:

模式客户端请求服务端响应适用场景
1. 一元 RPC (Unary)1 条1 条普通接口调用,如同步函数
2. 服务端流式 (Server Streaming)1 条N 条(流)服务端持续推送数据
3. 客户端流式 (Client Streaming)N 条(流)1 条客户端批量上传或持续上报
4. 双向流式 (Bidirectional Streaming)N 条(流)N 条(流)实时全双工交互

1. 一元 RPC (Unary RPC)​

这是最“经典”的 RPC 模式,和普通的 HTTP 请求/响应完全一致。

  • 行为:客户端发送一个请求,阻塞等待,直到服务端返回一个响应。
  • proto 定义:不加 stream 关键字。
    rpc GetUser (UserIdRequest) returns (UserResponse);
  • 典型场景:登录验证、获取用户详情、订单查询等常规读写操作。

2. 服务端流式 RPC (Server Streaming RPC)​

客户端发送一个请求,服务端会返回一个数据流(可以持续发送多条消息)。

  • 行为:客户端发起请求后,会持续监听(非阻塞),服务端可以多次调用 Send() 方法发送数据,直到发送完毕并告知客户端结束。
  • proto 定义:在 returns 前加 stream。
    rpc GetStockPrice (StockRequest) returns (stream StockPrice);
  • 典型场景:
    • 实时行情:客户端请求某只股票,服务端持续推送最新股价。
    • 大日志导出:客户端请求导出一个月的大文件日志,服务端分块流式返回,避免内存溢出。
    • 进度推送:客户端发起长耗时任务(如视频转码),服务端通过流实时返回当前进度百分比。

3. 客户端流式 RPC (Client Streaming RPC)​

客户端发送一个数据流到服务端,服务端处理完所有数据后,只返回一个最终响应。

  • 行为:客户端可以多次调用 Send() 发送数据,发送完成后调用 CloseAndRecv() 告知服务端“我发完了”。服务端接收完所有数据,处理完毕后返回一个响应。
  • proto 定义:在 request 前加 stream。
    rpc UploadFile (stream FileChunk) returns (UploadStatus);
  • 典型场景:
    • 大文件上传:客户端将大文件切成多个数据块(Chunk)分片上传。
    • 物联网数据上报:传感器设备不断向服务器上报温度、湿度数据,服务器汇总计算后返回一个平均指标。

4. 双向流式 RPC (Bidirectional Streaming RPC)​

这是最强大的模式。客户端和服务端各自独立地维持一个读写数据流,双方可以同时发送和接收消息。

  • 行为:调用开始后,双方维持长连接。客户端和服务端的发送和接收完全解耦且异步(顺序由业务逻辑决定,但消息顺序在各流内是保序的)。
  • proto 定义:在 request 和 returns 前都加 stream。
    rpc Chat (stream ChatMessage) returns (stream ChatMessage);
  • 典型场景:
    • 实时聊天室:用户发送消息的同时,实时接收其他人发送的消息。
    • 实时游戏同步:客户端发送玩家操作指令,服务端推送其他玩家的位置状态。
    • 分布式协同:两个微服务之间建立长连接,实时交换监控状态或配置变更通知。

⚠️ 实现原理上的一点重要补充​

理解双向流时,要记住一个底层特性:双向流并不是一条“双绞线”,而是两条独立的“单向流水线”(基于 HTTP/2 的多路复用)。这意味着:

  1. 服务端可以等到接收完所有客户端消息再开始发送响应,也可以在刚收到第一条请求时就开始发送响应,完全不依赖于客户端的发送进度。
  2. 每条流内的消息顺序有保证(先发的先到),但客户端流和服务端流之间的消息顺序无法相互保证。

如何选择?​

  • 服务间同步调用:直接用 一元 RPC,简单高效。
  • 数据量过大:用 服务端流(拉取大数据)或 客户端流(上传大数据)。
  • 需要实时推送:用 服务端流(如推送新闻)或 双向流(如即时通讯)。
  • 两端都需要随时发送数据:请毫不犹豫选择 双向流式。