gRPC (proto3) Unary RPCとStreaming RPCの使い分けと遅延比較

gRPC Protobuf Backend Performance
結論

単発リクエストには Unary、継続データ転送には Streaming(L7ロードバランサ必須)を使います。

// gRPC (proto3) 公式仕様:.proto での通信定義
syntax = "proto3";

package log.v1;

service LogService {
  // 1. Unary RPC (単発の取得・更新)
  rpc GetLog (LogRequest) returns (LogResponse);

  // 2. Server Streaming RPC (ログの連続ストリーミング)
  rpc StreamLogs (LogRequest) returns (stream LogResponse);
}

gRPC公式仕様:4つの RPC 通信モデル比較

gRPC公式ドキュメント(grpc.io/docs/guides/concepts/)で定義されている通信モデルの比較です。

通信モデルリクエスト件数レスポンス件数主なユースケース
Unary RPC1件1件通常のAPIリクエスト、CRUD操作
Server Streaming1件複数件 (連続)大容量ログ出力、チャット履歴受信
Client Streaming複数件 (連続)1件大容量ファイルアップロード、メトリクス送信
Bidirectional複数件 (連続)複数件 (連続)双方向リアルタイム通信、ゲームサーバー

実際に起こる障害:L4 ロードバランサによる TCP コネクション偏り事故

Streaming RPC は HTTP/2 の単一 TCP コネクションを持続接続(Long-lived Connection)して通信を行う特性を持ちます。

AWS NLB などの L4 (Layer 4) ロードバランサ 経由で Streaming RPC を配置した場合、L4 は「TCPコネクション単位」で振り分けるため、すべてのストリームリクエストが最初に接続された1台のバックエンドPodに集中してCPUが100%に張り付き、他サーバーが遊んでしまう負荷偏り障害 が発生します。


設計手順

  1. 単発のレスポンス取得にはシンプルな Unary RPC を優先選択する
  2. 大容量ファイル転送や継続イベント通知には HTTP/2 フレームのオーバーヘッドを削れる Streaming RPC を使用する
  3. Streaming RPC を採用する場合は、Envoy や AWS ALB / Istio などの L7 (Layer 7) ロードバランサ を導入し、ストリーム単位での負荷分散を設計する