ゲームラグ白書 › TCP再送の根本原因
接続中のNAT・ロードバランサーのマッピング期限切れ NAT / load balancer mapping expired mid-connection
原因ID rt-mapping · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・ネットワークインフラ, インフラチーム・サーバーインフラ
図と実験のあるメインページでこのカードを開く →
アイドル接続のマッピング(この接続をどこに転送するかを記録したエントリ)を中間機器が消すと、次に送るパケットは転送されません。再送だけを繰り返した末に切断されるか、機器が接続拒否(RST)を返してすぐに切断されます。
なぜ しばらくパケットのやり取りがない接続(離席、ロビー) → すると ルーターのNAT・通信事業者のCGNAT・ファイアウォール・ロードバランサー・クラウドのセキュリティグループがアイドル状態のマッピングを削除 → 画面では 再び動いた瞬間に再送が続いた末に切断、またはすぐに切断
- 症状
- 切断, フリーズ
- 要因
- パケットロス
- 誰に起きるか
- 自分だけ, 特定の地域・ISP
- いつ
- しばらく放置した後
- 担当
- 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・ネットワークインフラ, インフラチーム・サーバーインフラ
- ゲーム開発チームの対応
- クライアント:最も短いアイドルタイムアウトの半分以下の間隔でハートビートを送る(ユーザーのルーター・通信事業者のCGNATのマッピングは内側から出ていくパケットでしか確実に更新されず、そのタイムアウトは自社では変えられないため、クライアントが送る)、切断されたら自動で再接続。サーバー:ハートビートに応答し、一定時間受信できなければ接続を先に整理(TCP keepaliveの間隔を縮める(TCP_KEEPIDLEなどのソケットオプション)、TCP_USER_TIMEOUTで早く検知)、セッショントークンで引き継ぐ。
- インフラチームの対応
- ネットワーク:経路上のファイアウォール・ロードバランサーのアイドルタイムアウトをまとめてゲーム開発チームに共有、自社のファイアウォール・ロードバランサーは必要なら延ばす。サーバー機器・OS:クラウドのセキュリティグループの接続追跡時間を確認してゲーム開発チームに共有。
- 数値の目安
- TCPのマッピングを保持する時間は、機器によって数分から数時間までまちまちです。クラウドのセキュリティグループが接続を追跡する設定の場合、AWSのNitro v6インスタンスタイプはデフォルトで350秒後に追跡エントリを削除します(その他のタイプは5日、「クラウドのセキュリティグループによる接続追跡の期限切れ」の項目を参照)。LinuxのTCP keepaliveはデフォルト値が「2時間アイドルなら確認」なので、ほとんどの機器より遅くなります。
- グラフでは
- 接続が一斉に切れる · 切断数、切断前のアイドル時間
- 確認箇所
- 切断された接続の最後の数分をサーバー側のパケットキャプチャで確認し、生きている接続はss -tiのlastsnd・lastrcv(最後に送信・受信してから経過したms)でアイドル時間を確認。nstatのTcpExtTCPAbortOnTimeout(タイマーが切れて接続をあきらめた数)もあわせて確認
- 該当する場合
- 切断された接続はどれも、直前のアイドル時間が同じような値(経路上の機器のアイドルタイムアウト、例:AWS Nitro v6インスタンスのセキュリティグループの350秒)を超えており、アイドル後の最初のパケットからACKのない再送だけが続いてあきらめるか、すぐにRSTが返ってくる
- 該当しない場合
- アイドル時間と関係なくプレイ中にも切断されるなら別の原因(「経路変更・ECMPの不良経路」「ファイアウォール・接続追跡による破棄」)。ハートビートが最も短いアイドルタイムアウトの半分以下の間隔でやり取りされている接続なら、この原因からは除外
- 確認手段
- インフラのツールで確認(ゲームコード不要)
出典
- RFC 5382: NAT Behavioral Requirements for TCP IETF
TCPのNATの接続アイドルタイムアウトは2時間4分以上であるべきという推奨(機器がアイドルセッションを先に消す可能性があることが前提) - RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP IETF
NATのマッピングは内側から出ていくパケットで更新されなければならず(REQ-6)、外から入ってくるパケットによる更新は任意(UDPの場合) - Amazon EC2 security group connection tracking AWS
TCPのアイドル追跡タイムアウトのデフォルト値は、Nitro v6インスタンスタイプで350秒、その他のタイプで432,000秒(5日)。5分より短い間隔のkeepaliveを推奨 - IP Sysctl Linux kernel
tcp_keepalive_timeのデフォルト値は2時間 - tcp(7) — Linux manual page Linux man-pages
TCP_KEEPIDLE(keepaliveを始める前のアイドル時間)、TCP_USER_TIMEOUT(確認応答のないデータを待ち続け、接続を閉じるまでの時間) - RFC 5482: TCP User Timeout Option IETF
TCPユーザータイムアウト:送ったデータに確認応答がないまま、どれだけ経過したら接続を閉じるか - ss(8) — Linux manual page iproute2
ss -iのlastsnd・lastrcv:最後に送信・受信してからの経過時間(ms) - SNMP counter Linux kernel
TcpExtTCPAbortOnTimeout:TCPのタイマーが切れ、RSTなしで接続をあきらめた数
あわせて読みたい原因
同じ層:TCP再送の根本原因
同じ症状(切断)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る