#このページで確認できること
- gRPC の1回のRPCが HTTP/2 の1ストリームにどうマッピングされるかを確認する
- grpcurl で unary RPC を呼び、headers / contents / trailers の3点を確認する
- 「HTTP 200 なのに
grpc-statusはエラー」という gRPC 特有の見え方を理解する - 観察するヘッダー:
content-type: application/grpc、te: trailers、trailers のgrpc-status/grpc-message
実装上の制約: デモ用の EchoService はローカル観測専用としてリポジトリに同梱しています(demos/grpc-go/)。公開環境では起動しない方針です。docker compose up grpc で localhost:50051 に reflection 有効で起動し、以下のコマンド例がそのまま動きます。
#HTTP/2 へのマッピング
gRPC の1回のRPCは、HTTP/2 の1ストリームに対応します。ワイヤ上は次のようなHTTPメッセージです。
request (同梱h2cデモのHTTP/2疑似ヘッダー例)- 正常に成立したgRPC応答はHTTP 200: RPCの成否はtrailersの
grpc-statusで判断する(0 = OK, 5 = NOT_FOUND, 14 = UNAVAILABLE など)。トランスポート障害や非gRPC応答ではHTTP 200以外になることもある。 te: trailers: HTTP/2経路がtrailersを扱えることを確認するためのシグナル。標準gRPCに必要なtrailersが変換・欠落する経路では、RPCステータスを正しく伝えられない。- メッセージフレーミング: HTTP/2 DATAのペイロード上に「圧縮フラグ1バイト + 長さ4バイト + メッセージ本体」の列が流れる。gRPCメッセージ境界とDATAフレーム境界は一致せず、1メッセージが複数DATAにまたがる場合もある。
#4つのRPC形式
participants: Client, Server Client -> Server: HEADERS (:path /lab.EchoService/Echo) Client -> Server: DATA (request message) + END_STREAM Server --> Client: HEADERS (:status 200) Server --> Client: DATA (response message) Server --> Client: HEADERS (trailers: grpc-status 0) + END_STREAM
participants: Client, Server Client -> Server: HEADERS + DATA (request) + END_STREAM Server --> Client: DATA (message 1) Server --> Client: DATA (message 2) Server --> Client: DATA (message 3) Server --> Client: trailers (grpc-status 0) + END_STREAM
| 形式 | クライアント→ | →サーバー | 用途例 |
|---|---|---|---|
| unary | 1メッセージ | 1メッセージ | 通常のAPI呼び出し |
| server streaming | 1メッセージ | 複数メッセージ | ログ購読、フィード配信 |
| client streaming | 複数メッセージ | 1メッセージ | ファイルアップロード、メトリクス送信 |
| bidirectional | 複数メッセージ | 複数メッセージ | チャット、リアルタイム同期 |
#grpcurl での観測
grpcurl は gRPC 版 curl。server reflection が有効なサーバーならスキーマ取得から呼び出しまでできます。
デモサーバーの起動 (リポジトリ同梱)$ docker compose up grpc # localhost:50051 に lab.EchoService が起動する (reflection 有効, h2c)grpcurl
# サービス一覧(server reflection 使用) $ grpcurl -plaintext localhost:50051 list # サービスの定義を確認 $ grpcurl -plaintext localhost:50051 describe lab.EchoService # unary RPC を呼ぶ $ grpcurl -plaintext -d '{"message":"hello"}' \ localhost:50051 lab.EchoService/Echo # server streaming RPC (3回に分けて返る) $ grpcurl -plaintext -d '{"message":"hello"}' \ localhost:50051 lab.EchoService/EchoStream # -v でヘッダー・trailers も表示 $ grpcurl -plaintext -v -d '{"message":"hello"}' \ localhost:50051 lab.EchoService/Echo出力例 (grpcurlのバージョンで表示は異なる)
grpc-status: 0はワイヤ上のtrailersで送られますが、grpcurlはこれをRPCステータスとして処理するため、成功時の Response trailers received を (empty) と表示するバージョンがあります。ワイヤ上の実際のtrailersはWireshark等と併せて確認してください。
-plaintext(h2c、TLSなしHTTP/2)で接続し、メッセージサイズ上限64KB、同時ストリーム32、最大コネクションidle 60秒、ペイロード非記録を設定しています。方針は docs/demos-local-only.md を参照してください。
#観測ポイント
| grpcurl | -v で headers / contents / trailers の3点セットを確認する。エラー時は grpc-status と grpc-message を確認する。 |
|---|---|
| DevTools | 一般的なブラウザAPIは、標準gRPCが必要とするHTTP/2制御やtrailersをそのまま公開しない。ブラウザ向けにはgRPC-Webを使い、対応プロキシ等で標準gRPCへ変換する構成が一般的。 |
| Proxy | 標準gRPCはHTTP/2マッピングを前提とする。HTTP/1.1自体にもtrailersはあるが、単純なHTTP/1.1化ではgRPCの意味論は保持されない。gRPC-Web等として明示的に変換するか、HTTP/2とtrailersをエンドツーエンドで維持する必要がある。 |
| tcpdump / Wireshark | 平文(h2c)なら Wireshark が grpc / protobuf ディセクタでデコードできる。フィルタ: grpc。.proto を登録するとメッセージ内容も展開される。 |
| TLS inspection | 装置がh2とtrailersを正しく維持できるかを確認する。復号→再暗号化の過程でtrailersを変換・欠落させる構成ではgRPCが失敗し得る。directで成功し、装置経由で UNAVAILABLE になる場合は経路差を調べる。 |
#関連
gRPC を理解するには土台の HTTP/2(ストリーム、フレーム、trailers)の理解が前提になります。双方向通信の代替としては WebSocket も比較対象です。