gRPCとは?仕組み・RESTとの違い・UDP/TCPの扱いを実装例つきで解説

gRPCは、Googleが開発したオープンソースのRPC(Remote Procedure Call=リモートプロシージャコール)フレームワークです。離れた場所にあるサーバーの関数を、まるで手元のローカル関数のように呼び出せるのが特徴で、特にマイクロサービス間の高速・効率的な通信で広く使われています。この記事では、gRPCとは何かという基本から、HTTP/2とProtocol Buffersを使う仕組み、REST APIとの違い、メリット・デメリット、そして実際に動かして確認したPythonの実装例までを順に解説します。「gRPCはUDPを使うのか」といったトランスポートの疑問や、HTTP/3(QUIC)対応、テレメトリ収集での使われ方など、実務でつまずきやすい点も具体的に取り上げます。

まとめ

gRPCは、HTTP/2とProtocol Buffersを土台に、リモートの処理をローカル関数のように呼び出せるGoogle発のRPCフレームワークです。小さく高速なデータ転送、強い型付け、多言語対応、4種類の通信方式といった特徴があり、特にマイクロサービス間の通信で大きな効果を発揮します。トランスポートは標準ではHTTP/2(TCP)で動作し、UDPは使いません(UDPベースのHTTP/3=QUIC対応は一部実装で実験段階)。一方で、ブラウザから直接使えない、バイナリでデバッグしにくいといった弱点もあるため、外部公開はREST、内部通信はgRPC、というように適材適所で使い分けるのが現実的です。まずは本記事の最小実装を手元で動かし、.protoの定義からコード生成、サーバー・クライアント実装という流れを体感してみてください。

gRPCとは何か

gRPCは、Googleが社内で長年使ってきた「Stubby」と呼ばれるRPC基盤をルーツに持ちます。Stubbyは2000年代初頭からGoogle内部で運用されていましたが独自仕様が多く外部公開されていませんでした。その後、通信部分を標準のHTTP/2に置き換えるなどして整理し、2015年にgRPCとしてオープンソース化されました。現在はCloud Native Computing Foundation(CNCF)のもとで開発が進められ、クラウドネイティブな分散システムの標準的な通信手段の一つになっています。

gRPCの土台にあるのはRPCという考え方です。RPCは、ネットワークの向こう側にある処理を、通信の細かい手続きを意識せずに「関数呼び出し」として扱えるようにする仕組みを指します。gRPCはこのRPCを、HTTP/2という高速なトランスポートと、Protocol Buffersという効率的なデータ形式の上で実現したものだと考えると分かりやすいでしょう。プログラミング言語に依存しないため、Goで書いたサーバーをPythonのクライアントから呼ぶ、といった言語をまたいだ連携も容易です。

gRPCの仕組み(3つの構成要素)

gRPCの仕組みは、大きく「HTTP/2」「Protocol Buffers」「スタブとチャネル」の3つに分けて理解すると整理しやすくなります。

HTTP/2:高速な通信路

gRPCは通信路にHTTP/2を使います。HTTP/2は、1本の接続の上で複数のやり取りを同時に流せる多重化、ヘッダーの圧縮、サーバーとクライアントが双方向にデータを流せるストリーミングといった特徴を持ち、従来のHTTP/1.1に比べて低遅延で効率的です。gRPCのストリーミング機能やパフォーマンスの高さは、このHTTP/2の性質に支えられています。

Protocol Buffers:効率的なデータ形式

gRPCは標準で、Protocol Buffers(protobuf)というデータのシリアライズ方式を使います。JSONやXMLのようなテキストではなくバイナリでデータを表現するため、サイズが小さく転送が高速です。やり取りするデータ構造とサービスのメソッドは、拡張子が「.proto」のテキストファイルにスキーマとして定義します。この定義からコンパイラが各言語向けのコードを自動生成するため、強い型付けと言語間の互換性が同時に得られます。

なお、gRPCとProtocol Buffersは混同されがちですが別物です。gRPCはRPCを実現する通信フレームワークであり、Protocol Buffersはそのデータの表現方式の一つにすぎません。gRPCのトランスポート(HTTP/2)やデータ形式は理屈の上では差し替えも可能ですが、標準ではHTTP/2とProtocol Buffersの組み合わせが使われます。

スタブとチャネル:呼び出しの入り口

クライアント側には「スタブ」と呼ばれる代理オブジェクトが用意されます。開発者はスタブのメソッドを普通の関数のように呼び出すだけで、実際のシリアライズやHTTP/2通信はスタブが裏側で処理してくれます。スタブはサーバーへの接続を表す「チャネル」を通じてリクエストを送り、サーバー側のgRPCサーバーがそれを受け取って処理し、結果を返します。これにより、ネットワーク通信の複雑さを開発者から隠せるのがgRPCの大きな利点です。

gRPCが使うトランスポート:TCP・UDP・HTTP/3(QUIC)の関係

「gRPC UDP」で検索する人は少なくありませんが、標準構成のgRPCはUDPを使いません。gRPCはHTTP/2の上で動作し、そのHTTP/2はTCPの上で動くため、gRPCの通信はTCPで行われます。高速=UDPという連想や、後述するHTTP/3の登場から混同が生じやすいだけで、いま広く使われているgRPCのトランスポートはTCPだと押さえておけば十分です。

TCPが使われるのは偶然ではありません。HTTP/2は1本のTCP接続上でストリームを多重化し、順序保証・再送・フロー制御といった信頼性のある配送を前提に設計されています。gRPCのストリーミングやエラー処理はこの土台に依存しているため、コネクションレスで到達保証のないUDPをそのまま差し替えることはできません。

一方で「UDPを使うgRPC」が現実味を帯びるのがHTTP/3です。HTTP/3はTCPではなくQUIC(もとはQuick UDP Internet Connectionsの略ですが、IETFの標準では頭字語ではなく名称と定義されています)というトランスポート上で動き、QUICはUDPの上に多重化・信頼性・暗号化(TLS 1.3相当)を再実装したものです。つまりgRPCがHTTP/3に対応すれば、その通信は結果的にUDPの上を流れることになります。

gRPC over HTTP/3への対応は、2026年時点ではまだ実験的な段階です。quic-goのHTTP/3実装を利用する構成や、標準ライブラリのhttpハンドラをそのまま使えるConnectRPCのような実装で先行して試せますが、すべての言語実装で安定・標準化されているわけではありません。採用を検討する際は、使う言語のライブラリが対応済みか公式ドキュメントで最新状況を確認してください。

HTTP/3(QUIC)に移す実利は、TCP由来のヘッドオブラインブロッキングの解消にあります。TCPでは1つのパケットロスが同じ接続上の全ストリームを待たせますが、QUICはストリームごとに独立して回復できます。加えて再接続時には0-RTTで復帰でき(新規接続は1-RTT)、IPアドレスが変わっても接続を維持できるコネクションマイグレーションを備えるため、Wi-Fiとモバイル回線を行き来するクライアントやパケットロスの多い経路で効果が出やすい構成です。ただしQUICはUDPを使うため、EnvoyやNGINXなどのロードバランサ・プロキシがHTTP/3(UDP)を処理できる必要があり、輻輳制御をユーザー空間で行う分サーバーのCPU負荷はHTTP/2より高くなりがちです(UDPのGSO/GROといったオフロードの普及で差は縮小しつつあります)。

実務上の判断としては、サーバー同士の内部通信であれば現状は標準のHTTP/2(TCP)で十分です。HTTP/3(QUIC=UDP)が効くのは、モバイルクライアントや高遅延・不安定な回線を相手にするケースなので、まずHTTP/2で構築し、そうした要件が明確になってからHTTP/3対応を検討するのが現実的です。

gRPCの4つの通信方式

gRPCは単純な1往復の通信だけでなく、HTTP/2のストリーミングを活かした4つの通信方式をサポートしています。用途に応じて使い分けられる点が、REST APIとの大きな違いの一つです。

  • Unary RPC(単一):1つのリクエストに対して1つのレスポンスを返す、もっとも基本的な形。通常の関数呼び出しに近い使い方です。
  • サーバーストリーミングRPC:1つのリクエストに対し、サーバーが複数のレスポンスを順次返します。一覧データの逐次配信などに向きます。
  • クライアントストリーミングRPC:クライアントが複数のリクエストを送り、サーバーが最後にまとめて1つのレスポンスを返します。大量データのアップロードなどに向きます。
  • 双方向ストリーミングRPC:クライアントとサーバーが同時に複数のメッセージを送受信します。チャットやリアルタイムなデータ処理に適しています。

gRPCとREST APIの違い

gRPCを検討する際にもっとも比較されるのがREST APIです。どちらもシステム間の通信に使われますが、設計思想と得意分野が異なります。主な違いを表に整理します。

項目 gRPC REST API
ベースのプロトコル HTTP/2 主にHTTP/1.1(HTTP/2も利用可)
データ形式 Protocol Buffers(バイナリ) JSON・XML(テキスト)
スキーマ定義 .protoで必須・強い型付け 任意(OpenAPI等で補完)
通信方式 4種類(単一・各種ストリーミング) 基本はリクエスト/レスポンス
速度・データサイズ 高速・小さい 相対的に低速・大きい
ブラウザからの直接利用 不可(grpc-web+プロキシが必要) 可能
人による可読性 低い(バイナリ) 高い(テキスト)
主な用途 マイクロサービス間・社内API・リアルタイム 公開Web API・ブラウザ向け

ざっくり言えば、ブラウザや外部公開を前提とする一般的なWeb APIではRESTが扱いやすく、サーバー同士の高頻度・低遅延な通信ではgRPCが力を発揮します。両者は排他的なものではなく、併用する構成もよく採られます(具体的な使い分けは後半で詳しく扱います)。なお、同じく代替として比較されることの多いGraphQLについては「GraphQLとは?REST APIとの違い・メリット・デメリットをわかりやすく解説」、RESTとの設計思想の違いは「REST APIとGraphQLの違いと使い分け|選定基準と運用コスト」もあわせて参考にしてください。

gRPCのメリットとデメリット

gRPCの主なメリットは、Protocol Buffersによる小さく高速なデータ転送、HTTP/2による多重化・低遅延、.protoスキーマに基づく強い型付け、そして多くの言語に対応したクロスプラットフォーム性です。さらに4種類の通信方式により、リアルタイムなストリーミング処理も標準で実装できます。

一方でデメリットもあります。.protoの設計やコンパイルといった独自の手順があるため学習コストがかかること、データがバイナリのためJSONに比べてデバッグやログ確認がしにくいこと、そしてブラウザから直接呼び出せない点です。ブラウザ対応にはgrpc-webとプロキシ(Envoyなどが代表的)を別途用意する必要があります。これらを踏まえ、どの通信をRESTのままにし、どこをgRPCへ寄せるかを見極めることが重要になります。

gRPCが向いている場面

gRPCがもっとも活きるのは、マイクロサービス間の内部通信です。サービスを小さく分割するアーキテクチャでは、サービス同士が頻繁に通信するため、低遅延で型安全なgRPCの利点が大きく効きます。マイクロサービスそのものの考え方は「マイクロサービスとは?モノリスとの違い・メリット・デメリットと選び方、モジュラモノリスまで整理」で詳しく扱っています。このほか、限られた帯域で効率よくデータを送りたいIoTデバイス間の通信や、双方向ストリーミングを使ったリアルタイム処理にも適しています。

gRPCによるテレメトリ収集(OTLPとストリーミングテレメトリ)

gRPCは、監視や可観測性のためのテレメトリ(メトリクス・ログ・トレースなどの観測データ)を集める経路としても広く使われています。protobufによる小さなペイロードとHTTP/2ストリーミングの組み合わせが、大量の観測データを低オーバーヘッドで継続的に送り続ける用途に合うためです。gRPCがテレメトリで使われる文脈は、大きく「アプリケーションの可観測性」と「ネットワーク機器の状態監視」の2つに分かれます。

アプリケーション側の代表例が、OpenTelemetryの標準プロトコルであるOTLP(OpenTelemetry Protocol)です。OTLPはgRPCとHTTPの両方のトランスポートを定義しており、gRPC版(OTLP/gRPC)はHTTP/2上でフロー制御・再送・確認応答を使うため、負荷がかかる状況でも配送の信頼性を保ちやすいのが特徴です。エージェントやCollectorが観測データを継続的にストリーム送信する構成で、事実上の標準的な選択肢になっています。テレメトリデータやOpenTelemetryそのものの全体像は「OpenTelemetry(OTel)とは|3つのシグナル・OTLP・Collector・Prometheusとの違いを解説」で詳しく解説しています。

もう一方が、ネットワーク機器のストリーミングテレメトリです。ルーターやスイッチはgRPCを使い、状態が変化したときやサンプル間隔ごとに、値をprotobufでコレクタへ「プッシュ」します。接続の張り方には2種類あります。コレクタ側から機器へ接続して購読する方式(dial-in)は、標準化されたgNMI(gRPC Network Management Interface)のSubscribe RPCがこれにあたり、機器がgRPCサーバー、コレクタがクライアントになります。逆に機器側からコレクタへ接続する方式(dial-out)は、Cisco・Juniperといったベンダー独自のgRPCサービスとして実装され(gNMIの仕様外)、NATやファイアウォールの内側からでも内向きポートを開けずにテレメトリを送り出せる利点があります。いずれの方式も、一定間隔で問い合わせる従来のSNMPポーリングに比べ、変化を細かい粒度で即時に取得できます。

どちらの用途も「gRPCをテレメトリの転送に使う」点は共通しますが、対象領域は異なります。アプリケーションの可観測性ならOTLP/gRPC、ネットワーク機器の状態監視ならgNMI、と用途で選び分けるのが基本です。継続的にデータを送るテレメトリには、4つの通信方式のうちサーバーストリーミングやクライアントストリーミングが自然に対応します。

gRPCとRESTの使い分け:採用判断のポイント

gRPCとRESTは優劣で選ぶものではなく、プロジェクトの性質に合わせて使い分けるものです。導入を迷ったときは、次のような観点で判断すると整理しやすくなります。

gRPCの採用が向いているのは、サーバー同士の内部通信が多いシステムです。具体的には、マイクロサービス間で頻繁に通信する構成、GoやJava・Python・Node.jsなど複数の言語が混在する環境、チャットやライブ配信のように双方向のリアルタイム通信が必要なケース、大規模なチームで.protoによってAPI仕様を型で厳密に管理したい場合などが挙げられます。すでにRESTでの通信がパフォーマンスのボトルネックになっているなら、内部通信をgRPCに置き換える効果は大きくなります。

一方で、次のような場合はRESTのほうが扱いやすい選択になります。ブラウザやモバイルアプリから直接呼び出す公開API、管理画面のようにシンプルなCRUD(作成・読み取り・更新・削除)が中心のシステム、RESTに慣れた少人数チーム、外部やパートナーのAPIとの連携が多いプロダクト、そしてプロトタイプやMVPのように開発・検証の速度を最優先したい段階です。これらの場面では、gRPCの学習コストやデバッグの手間が利点に見合わないことが多くなります。

現実的な進め方としては、まずRESTでシステムを構築し、通信のボトルネックが明確になった部分から内部通信をgRPCへ段階的に移行するアプローチが取りやすいでしょう。外部公開はREST、内部のサービス間はgRPC、というように両者を併用する構成も広く採られています。API設計そのものの基本的な考え方は「Google API設計ガイドの概要と良いAPI設計の基本ポイント【完全ガイド序章】」もあわせてご覧ください。

gRPCの実装例(Python・動作確認済み)

ここでは、もっとも基本的なUnary RPCを例に、最小構成のgRPCサーバーとクライアントをPythonで実装します。以下のコードは実際に動作を確認したものです。まずは通信の設計図となる.protoファイルを作成します。

▼ greeter.proto(サービスとメッセージの定義)

syntax = "proto3";

package greeter;

// サービス定義:1つのメソッドを持つ
service Greeter {
  // Unary RPC:1リクエストに対し1レスポンスを返す
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

次に、この.protoから各言語向けのコードを生成します。Pythonでは、必要なライブラリ(grpcioとgrpcio-tools)を導入したうえで、付属のコンパイラを使います。同じ.protoファイルからGoやJavaなど他言語のコードも生成できます。

▼ ライブラリの導入とコード生成(bash)

pip install grpcio grpcio-tools
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. greeter.proto

これで「greeter_pb2.py」(メッセージ定義)と「greeter_pb2_grpc.py」(サービス定義)が生成されます。生成されたコードを使ってサーバーを実装します。

▼ server.py(gRPCサーバー)

from concurrent import futures
import grpc
import greeter_pb2
import greeter_pb2_grpc

class GreeterServicer(greeter_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return greeter_pb2.HelloReply(message=f"Hello, {request.name}!")

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server)
    server.add_insecure_port("[::]:50051")
    server.start()
    print("gRPC server started on :50051")
    server.wait_for_termination()

if __name__ == "__main__":
    serve()

続いて、サーバーのメソッドを呼び出すクライアントを実装します。

▼ client.py(gRPCクライアント)

import grpc
import greeter_pb2
import greeter_pb2_grpc

def run():
    with grpc.insecure_channel("localhost:50051") as channel:
        stub = greeter_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(greeter_pb2.HelloRequest(name="World"))
        print("Server replied:", response.message)

if __name__ == "__main__":
    run()

サーバーを起動した状態で別のプロセスからクライアントを実行すると、次のように応答が返ります。スタブのメソッドを呼ぶだけで、リモートの処理をローカル関数のように利用できていることが分かります。

▼ 実行結果

Server replied: Hello, World!

このように、gRPCでは.protoでインターフェースを定義し、コードを生成し、サーバーとクライアントを実装する、という流れが基本になります。本番環境では、後述するTLSによる暗号化やエラーハンドリング、タイムアウト設定などを加えていきます。

よくある質問(FAQ)

gRPCのポート番号は決まっていますか?

gRPC専用に固定されたポート番号はありません。任意のポートを指定できます。ただし公式のチュートリアルやサンプルでは慣例的に「50051」がよく使われており、開発時の例として広く浸透しています。本番では用途に応じて自由に決めて構いません。

gRPCの通信は暗号化できますか?(TLS対応)

はい。gRPCはHTTP/2をベースにしているためTLSを容易に組み込めます。サーバーに証明書と秘密鍵を設定して通信を暗号化でき、クライアントとサーバーが互いに証明書を検証する相互TLS(mTLS)も利用できます。公開ネットワークを越える通信では、TLSによる暗号化が事実上の前提となります。

gRPCはブラウザから直接使えますか?

ブラウザからgRPCを直接呼び出すことはできません。gRPCはHTTP/2の機能を細かく利用するため、ブラウザのJavaScriptからはそのまま扱えないためです。ブラウザ対応にはgrpc-webという仕組みを使い、Envoyなどのプロキシを介して通信します。

gRPCはどの言語で使えますか?

Go、Java、Python、C++、C#、Node.js、Ruby、PHP、Kotlin、Dart など、主要な言語に幅広く対応しています。同じ.protoファイルから各言語向けのコードを生成できるため、異なる言語で書かれたサービス同士を接続できるのがgRPCの強みです。

関連記事

資料請求

RELATED POSTS 関連記事