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 RPC | 1件 | 1件 | 通常のAPIリクエスト、CRUD操作 |
Server Streaming | 1件 | 複数件 (連続) | 大容量ログ出力、チャット履歴受信 |
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%に張り付き、他サーバーが遊んでしまう負荷偏り障害 が発生します。
設計手順
- 単発のレスポンス取得にはシンプルな
Unary RPCを優先選択する - 大容量ファイル転送や継続イベント通知には HTTP/2 フレームのオーバーヘッドを削れる
Streaming RPCを使用する - Streaming RPC を採用する場合は、Envoy や AWS ALB / Istio などの L7 (Layer 7) ロードバランサ を導入し、ストリーム単位での負荷分散を設計する