跳转至

四种 RPC 通信模式详解

gRPC 支持四种不同的客户端与服务端交互模型。得益于 HTTP/2 原生的双向流传输能力,每种模式都在协议层得到了原生的支持。


1. 模式概览与选型

通信模式 请求数据量 响应数据量 关键字定义 典型业务场景
简单一元 (Unary) 1 1 rpc Method(Req) returns (Resp) 登录校验、商品详情查询、常规业务操作
服务端流式 (Server Streaming) 1 N rpc Method(Req) returns (stream Resp) 股票实时行情报送、长轮询替代、日志实时推送
客户端流式 (Client Streaming) N 1 rpc Method(stream Req) returns (Resp) 大文件分块上传、IoT 传感器批量数据汇总上报
双向流式 (Bidirectional Streaming) N N rpc Method(stream Req) returns (stream Resp) 实时视频会议信令、多人在线聊天、AI 交互对话

2. 一元 RPC (Unary RPC)

一元 RPC 是最直观的模式,行为与传统的 RESTful 请求或标准本地方法调用完全一致:客户端发送单个请求,服务端返回单个应答并关闭流。

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Server as 服务端

    Client->>Server: 发送请求头部 (HEADERS: path, metadata)
    Client->>Server: 发送消息载荷 (DATA: Request) [带 END_STREAM 标志]
    Server-->>Client: 发送响应头部 (HEADERS: :status=200, content-type)
    Server-->>Client: 发送响应载荷 (DATA: Response)
    Server-->>Client: 发送状态尾部 (HEADERS: grpc-status=0) [带 END_STREAM 标志]

契约定义

service OrderService {
  rpc GetOrder (GetOrderRequest) returns (GetOrderResponse);
}

3. 服务端流式 RPC (Server Streaming RPC)

客户端发送单个请求后,服务端建立流并持续推送多个响应消息,直到所有数据发送完毕后发送包含 grpc-status 的 Trailer 尾部关闭流。

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Server as 服务端

    Client->>Server: 发送请求 (HEADERS + DATA) [流客户端半关闭]
    Server-->>Client: 发送响应头 (HEADERS)
    loop 持续推流
        Server-->>Client: 推送响应分片 1 (DATA)
        Server-->>Client: 推送响应分片 2 (DATA)
        Server-->>Client: 推送响应分片 N (DATA)
    end
    Server-->>Client: 发送终止尾部 (Trailers: grpc-status=0) [全关闭]

契约定义与应用

service MarketService {
  // 订阅指定股票代码的实时行情流
  rpc SubscribeTicker (TickerRequest) returns (stream TickerUpdate);
}
适用场景: - 客户端发起订阅,服务端持续将变更事件推回。 - 大规模数据分页导出(相比单次返回巨大 JSON,流式推流能大幅降低服务端的内存暴涨)。


4. 客户端流式 RPC (Client Streaming RPC)

客户端获取流句柄后,可以按需、分批次写入多个请求消息。全部发送完毕后,通知服务端(Half-close 半关闭),服务端处理聚合逻辑并返回唯一的响应结果。

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Server as 服务端

    Client->>Server: 发送请求头 (HEADERS)
    loop 持续上传分片
        Client->>Server: 写入分片 1 (DATA)
        Client->>Server: 写入分片 2 (DATA)
        Client->>Server: 写入分片 N (DATA)
    end
    Client->>Server: 客户端关闭写入端 (Half-Close)
    Server-->>Client: 计算完成,返回单次响应 (DATA)
    Server-->>Client: 发送终止尾部 (Trailers: grpc-status=0)

契约定义与应用

service FileTransferService {
  // 分块上传文件,最终返回文件元数据和存储路径
  rpc UploadFile (stream FileChunk) returns (UploadSummary);
}

5. 双向流式 RPC (Bidirectional Streaming RPC)

双方完全解耦,各自独立使用读写流。客户端和服务端可以按任意顺序发送和接收消息——例如,服务端可以在收到请求后立刻回复,或者先缓冲全部请求再批量回复,亦或边收边发。

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Server as 服务端

    Client->>Server: 协商建流 (HEADERS)
    par 客户端写入流
        Client->>Server: 写入 Message A
        Client->>Server: 写入 Message B
    and 服务端写入流
        Server-->>Client: 响应 Message 1
        Server-->>Client: 响应 Message 2
        Server-->>Client: 响应 Message 3
    end
    Client->>Server: 客户端关闭写入 (Half-Close)
    Server-->>Client: 服务端传输完毕并发送 Trailers (全关闭)

契约定义与应用

service ChatService {
  // 实时双向聊天通道
  rpc JoinRoom (stream ChatMessage) returns (stream ChatMessage);
}
生产注意事项: 1. Goroutine / 线程泄漏防护:双向流通常在客户端和服务端各有一个常驻循环用于读取。务必监听上下文取消信号(ctx.Done()),在网络中断时及时退出循环并释放资源。 2. 流量控制:若一方发送速度远快于另一方消费速度,应充分利用 HTTP/2 提供的 Window Update 窗口流控机制,避免接收端内存堆积。