😊

gRPC Client streaming 通信の内容を Wireshark で確認する

2022/08/06に公開

gRPC Client streaming 通信のパケットを解析してみます。

Wireshark の設定方法などは過去の記事に簡単に書いているので参考にしてください。

解析対象のサーバ・クライアントプログラムも前回のものを使います。

パケット解析

Client streaming RPC

処理の流れ

  1. クライアントが RecordTransform に Transform を複数件投げる
  2. サーバが OK を返す

  • No.249 - 251 c <=> s
    • TCP 3 way handshake
  • No.252 - 253 c => s
    • HTTP2 Magic
  • No.254 - 261 c <=> s
    • HTTP2 Settings
  • No.262 - 263 c => s
    • HTTP2 Header POST /grpc.GameService/RecordTransform
  • No.264 - 265 c => s
    • HTTP2 DATA grpc.Transform
    • HTTP2 DATA grpc.Transform
    • (snip 64件続く)
  • No.266,268 s => c
    • HTTP2 WINDOW_UPDATE
  • No.267,270 c => s
    • HTTP2 DATA grpc.Transform
    • HTTP2 DATA grpc.Transform
    • (snip 36件続く)
    • HTTP2 DATA End Stream
  • No.269,272 c => s
    • HTTP2 PING
  • No.274 - 275 s => c
    • HTTP2 Headers 200 OK
    • HTTP2 DATA /grpc.GameService/RecordTransform, Response
    • HTTP2 Headers End Stream
  • No.276 - 277 c => s
    • HTTP2 WINDOW_UPDATE
  • No.278 - 279 s => c
    • HTTP2 PING
  • No.280
    • TCP rst

TCP 3 way handshake, HTTP2 Magic, HTTP2 Settings までは Unary RPC, Server streaming RPC と変わらず。

No.262 - 265,267,270 がクライアントがリクエストしているところ。

  1. No.262 - 263 でヘッダ(168 Bytes)を送信
  2. No.264 - 265 で Transform データ(3136 Bytes)を 64 件送信
  3. No.267,270 で Transform データ(1801 Bytes)を 36 件送信

Transform は 1 件あたり 48 Bytes でデータ構造は前回と変わらず。

一つ分からないところが出てきました。

前回の server streaming の解析では見逃してしまっていたけれど、一度目の DATA 送信の時点で 3136 Bytes を送信できているのは何故だろう・・・。

No.256 の HTTP2 Setting のやりとりの時点でサーバからクライアントに対して、Max frame size: 16,384 が送られていて、クライアントからも ack を返している。

このフレームサイズを超えてデータが送られた場合、frame_size_error になると思っていたけれど、サーバ側でもエラーとして扱っていない

悩んだ挙げ句、RFC9113 を改めて確認して、自分の認識の間違いに気づきました。

HTTP2 フレーム ≠ TCP セグメント

1 つの TCP セグメントの中には複数の HTTP2 フレームが格納されている。
Max frame size は HTTP2 フレームに対する上限なので、フレームの Length がこの値を超えなければエラーにはならない。
・・・ということなのかな。

今回のケース

  • 3136 Bytes の TCP セグメントの中に 39 Bytes の DATA フレームが 64 件格納されている
  • どのフレームも Max frame size: 16,384 未満

おまけ 実環境に近い環境で再試験

MTU, MSS が 1500 を大きく上回っているのは、同一 PC 上での loopback インターフェイス環境で MSS が 65,475 Bytes になっているからなので TCP 的には問題ないです。

念のため別 PC をクライアントにして試験してみると、期待通り TCP セグメントが 1500 に近いサイズで区切られるようになりました。

Summary

Client streaming RPC は方向が違うだけで Server streaming RPC と大きな違いはなさそうです。
gRPC のパケット解析のつもりが、悩んで調査していた範囲はほぼ HTTP2 の範囲でした。
gRPC を理解する為には HTTP2 の理解が必要ですね。

Discussion