gRPC

Google が開発した高性能な RPC フレームワークで、Protocol Buffers を用いた効率的なサービス間通信を実現する

RPC

gRPC とは

gRPC は、Google が 2015 年にオープンソースとして公開した高性能な RPC (Remote Procedure Call) フレームワークである。HTTP/2 上で Protocol Buffers (protobuf) を使い、言語に依存しない型安全な API 契約をサービス間で共有する。クライアントはローカル関数を呼び出すかのようにリモートサーバーのメソッドを実行できる。

Google 社内では Stubby という RPC フレームワークが 2001 年から使われており、gRPC はその後継としてオープンソース化されたものだ。現在は CNCF (Cloud Native Computing Foundation) のプロジェクトとして管理されている。

REST API との比較

観点 gRPC REST API
プロトコル HTTP/2 HTTP/1.1 or HTTP/2
データ形式 Protocol Buffers (バイナリ) JSON (テキスト)
スキーマ .proto ファイル (必須) OpenAPI (任意)
ストリーミング 双方向対応 非対応 (SSE で片方向)
ブラウザ対応 gRPC-Web 経由 ネイティブ対応
コード生成 自動生成 (多言語) 手動 or ツール
ペイロードサイズ 小さい (バイナリ) 大きい (テキスト + キー名)
人間の可読性 低い (バイナリ) 高い (JSON)

protobuf のバイナリエンコーディングは JSON と比べてペイロードサイズが 3〜10 倍小さく、シリアライズ/デシリアライズも高速だ。マイクロサービス間で秒間数万リクエストを処理する場合、この差は無視できない。

Protocol Buffers の定義

syntax = "proto3";

service OrderService {
  rpc CreateOrder (CreateOrderRequest) returns (Order);
  rpc GetOrder (GetOrderRequest) returns (Order);
  rpc ListOrders (ListOrdersRequest) returns (stream Order);  // Server Streaming
}

message CreateOrderRequest {
  string customer_id = 1;
  repeated OrderItem items = 2;
}

message Order {
  string id = 1;
  string customer_id = 2;
  OrderStatus status = 3;
  int64 total_cents = 4;  // 金額はセント単位の整数で表現
}

enum OrderStatus {
  PENDING = 0;
  CONFIRMED = 1;
  SHIPPED = 2;
}

.proto ファイルから TypeScript、Go、Java、Python など各言語のクライアント/サーバーコードが自動生成される。API の型安全性がコンパイル時に保証される。

4 つの通信パターン

パターン 方向 用途
Unary 1 リクエスト → 1 レスポンス 通常の API 呼び出し (REST と同等)
Server Streaming 1 リクエスト → N レスポンス ログストリーム、検索結果の逐次返却
Client Streaming N リクエスト → 1 レスポンス ファイルアップロード、センサーデータの一括送信
Bidirectional Streaming N リクエスト ↔ N レスポンス チャット、リアルタイム同期

REST API では実現が難しい双方向ストリーミングが、gRPC ではネイティブにサポートされている。

採用の判断基準

gRPC が適するケース

  • バックエンドのマイクロサービス間通信 (高スループット、低レイテンシが求められる)
  • 多言語環境 (Go のサービスと TypeScript のサービスが通信する)
  • ストリーミングが必要な場面 (リアルタイムデータ、大量データの逐次処理)
  • 厳密な API 契約が必要な場面 (型安全性、後方互換性の管理)

REST API が適するケース

  • ブラウザとの直接通信 (gRPC-Web は追加のプロキシが必要)
  • 外部パートナーへの API 公開 (JSON の方が広く理解されている)
  • シンプルな CRUD API (gRPC のセットアップコストが見合わない)
  • デバッグのしやすさを重視する場面 (JSON は人間が読める)

実務では、外部向けは REST API、内部のサービス間通信は gRPC というハイブリッド構成が一般的だ。

.proto ファイルの管理

チーム間で .proto ファイルを共有する方法が運用上の重要な課題になる。

  • モノレポ: 全サービスの .proto を 1 つのリポジトリで管理。変更の影響範囲が一目で分かる
  • 専用リポジトリ: .proto ファイルだけを管理するリポジトリを作り、各サービスが参照する
  • Buf Registry: Buf (protobuf のツールチェーン) のレジストリで .proto をパッケージとして配布する

後方互換性の管理も重要だ。フィールド番号の再利用や必須フィールドの追加は破壊的変更になる。buf breaking コマンドで CI に互換性チェックを組み込む。

// gRPC のサービス定義
service OrderService {
  rpc CreateOrder (CreateOrderRequest) returns (Order);
  rpc GetOrder (GetOrderRequest) returns (Order);
  rpc ListOrders (ListOrdersRequest) returns (stream Order);
}

実践的な知識は関連書籍でも得られる。

関連用語