한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

ゲームラグ白書 › TCP再送の根本原因

ゼロウィンドウ(再送のように見える停止) Zero window, often mistaken for retransmission

原因ID rt-zero-window · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・サーバーインフラ

図と実験のあるメインページでこのカードを開く →

受信側のプログラムがソケットを読むのが間に合わず、バッファが満杯になると、送信側は送信を止めてゼロウィンドウプローブだけを送ります。回線の問題ではありません。

なぜ クライアントのフレームが止まる、サーバーのスレッドがブロックされるなどでソケットを読めない → すると 受信ウィンドウが0になり、送信側は送信を止めてプローブだけを送る(間隔がだんだん延びる) → 画面では 止まった後に早送り。パケットキャプチャに「ZeroWindow」が見え、パケットロスはない

症状
フリーズ, 早送り
要因
ストール
誰に起きるか
自分だけ, サーバー全体
いつ
人が集中したとき, ときどきランダムに
担当
主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・サーバーインフラ
ゲーム開発チームの対応
パケットキャプチャでZeroWindowを送った側(ソケットを読めていない側)をまず確認、ネットワークの受信は別スレッドで読み続ける、受信バッファを適切なサイズに。クライアント:ロード・GCのようなフレーム停止の原因を解消。サーバー:ソケットを読むスレッドがブロックされる原因を解消。
インフラチームの対応
サーバーのnstat TcpExtTCPToZeroWindowAdv(サーバーが受信ウィンドウを0と通知した回数)を監視に追加(増えればサーバー側の問題なのでサーバー開発に連絡)、サーバー側のパケットキャプチャを提供。
グラフでは
途切れた後にまとめて到着 · 接続ごとの受信量、ゼロウィンドウの回数
確認箇所
パケットキャプチャでWiresharkのフィルターtcp.analysis.zero_windowを使い、ウィンドウ0を通知した側を探す。サーバーのnstatでは、TcpExtTCPToZeroWindowAdv(サーバーがウィンドウ0を通知)とTcpExtTCPWinProbe(相手のウィンドウ0に対してプローブを送信)を分けて確認し、サーバーのソケットのRecv-Q(ssで表示される、プログラムがまだ読んでいないバイト数)を確認
該当する場合
止まっている間に再送はなく、ゼロウィンドウとプローブだけがやり取りされる。サーバーのTcpExtTCPToZeroWindowAdvやサーバーのソケットのRecv-Qが増えるならサーバーの読み出しが間に合っていない。TcpExtTCPWinProbeが増えるならクライアントの読み出しが間に合っていない
該当しない場合
キャプチャにゼロウィンドウがなく、同じデータが再度送られているなら、原因はパケットロスか不要な再送
確認手段
インフラのツールで確認(ゲームコード不要)
実際の事例
Roblox 2021: Robloxの73時間障害:サービスディスカバリ(Consul)クラスターでの競合

出典

  1. RFC 9293: Transmission Control Protocol (TCP) IETF
    受信ウィンドウが0なら送信側はゼロウィンドウプローブを送り、プローブの間隔は指数的に延ばす
  2. 7.5. TCP Analysis Wireshark
    TCP ZeroWindow:受信側がウィンドウ0を通知し、送信側に送信を止めさせたパケット
  3. Display Filter Reference: Transmission Control Protocol Wireshark
    tcp.analysis.zero_window、tcp.analysis.zero_window_probeの表示フィルター
  4. SNMP counter Linux kernel
    TcpExtTCPToZeroWindowAdv:受信ウィンドウを0以外の値から0に変えて通知した回数
  5. net/ipv4/proc.c Linux kernel
    nstatに表示されるカウンター名TCPToZeroWindowAdv・TCPWinProbe
  6. net/ipv4/tcp_output.c Linux kernel
    TCPWinProbe:相手の受信ウィンドウが0のときに送るプローブ(tcp_send_probe0)ごとに増加
  7. net/ipv4/tcp_diag.c Linux kernel
    ssのRecv-Qは、確立済みの接続では、受信したがプログラムがまだ読んでいないバイト数

あわせて読みたい原因

同じ層:TCP再送の根本原因

同じ症状(フリーズ)を起こすほかの層の原因

図と実験のあるメインページでこのカードを見る