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

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

接続要求(SYN)の再送 SYN retransmission on connect

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

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

接続要求が接続待ちキュー(backlog)のあふれやファイアウォールの遮断で消えると、クライアントOSは1秒後から間隔を延ばしながら送り直します。

なぜ メンテ明けの接続の殺到でサーバーの接続待ちキューがあふれる、またはファイアウォール・DDoS対策がSYNを破棄 → すると クライアントOSが1秒後から決まった間隔でSYNを再送(以前のLinuxは1秒 → 2秒 → 4秒) → 画面では 接続ボタンを押してから1秒、3秒のようにきりのいい秒数だけ遅れ、失敗が続くと接続不可・無限ロード

症状
接続不可・無限ロード
要因
パケットロス
誰に起きるか
サーバー全体, 特定の地域・ISP
いつ
接続直後・メンテ明け
担当
主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, インフラチーム・ネットワークインフラ, ゲーム開発チーム・クライアント開発
ゲーム開発チームの対応
サーバー:listenのbacklog引数を増やす(somaxconnとあわせて)、ゲームサーバーがacceptを遅れずに呼ぶようにする、ログイン待機列の仕組み。クライアント:接続の再試行間隔を延ばす(ランダムに分散)。
インフラチームの対応
サーバー機器・OS:サーバーの接続待ちキューのあふれはnstatのTcpExtListenOverflows・TcpExtListenDropsとログの「Possible SYN flooding」警告で確認、somaxconnを増やす(listenの引数とあわせて)、SYN Cookie。ネットワーク:ファイアウォール・DDoS対策のSYN制限を緩和。
数値の目安
Linux(Androidを含む)の最初のSYN再送は1秒後です。以前のカーネルはその後間隔を2倍ずつ延ばし、1、3、7、15秒…の時点で再送、6.5以降は1、2、3、4、5秒の時点で5回送り直した後に2倍ずつ(7、11、19秒…)間隔を延ばします(tcp_syn_linear_timeouts=4)。Androidスマホは、OSをアップデートしても発売時のカーネルを使い続けることが多いため、同じAndroidバージョンでも端末ごとに異なる場合があります。どちらの場合も、すべて失敗すると約2分後にあきらめます。Windowsはバージョンと設定によって1秒または3秒から延びていき、送り直す回数が2〜4回なので20〜30秒であきらめます(そのPCの値はnetsh int tcp show globalのMax SYN Retransmissionsで確認)。
グラフでは
接続直後・メンテ明けに急増 · 接続試行数、接続待ちキューのあふれ数
確認箇所
サーバーのnstatでTcpExtListenOverflows・TcpExtListenDropsとdmesgの「Possible SYN flooding on port」警告を確認し、ss -lntで待ち受けソケットのRecv-Q(acceptを待っている接続数)がSend-Q(backlogの上限)に達していないか確認。サーバー側のキャプチャで、SYNが届いているか、SYN-ACKを返しているかを確認
該当する場合
メンテ明けの接続殺到時にTcpExtListenOverflowsが増え、Recv-QがSend-Qに張り付いている。キャプチャでは、同じクライアントのSYNが秒単位の間隔で再び届いているのに、サーバーが応答しない
該当しない場合
SYNがサーバーまで届かず、サーバーのカウンターも変わらないなら、前段のファイアウォール・DDoS対策が破棄しているので、その機器のSYN制限・ドロップログを確認。サーバーがSYN-ACKを送っているのに接続が遅いなら、戻り方向のパケットロス
確認手段
インフラのツールで確認(ゲームコード不要)

出典

  1. include/net/tcp.h Linux kernel
    最初のRTO TCP_TIMEOUT_INIT = 1秒(RFC 6298の初期値)
  2. RFC 6298: Computing TCP's Retransmission Timer IETF
    初期RTOは1秒、再送のたびに2倍
  3. IP Sysctl Linux kernel
    tcp_syn_retriesのデフォルトは6、tcp_syn_linear_timeoutsのデフォルトは4(SYNのRTOは1、1、1、1、1、2、4…)、最後の再送は67秒後・あきらめるのは131秒後、somaxconnのデフォルトは4096、tcp_syncookiesのデフォルトは1
  4. tcp: make the first N SYN RTO backoffs linear Linux kernel
    SYN再送の最初の部分を一定間隔に変えたコミット、Linux 6.5から(デフォルトの4はmacOS・iOSの方式にならったもの)
  5. Android common kernels Android (Google)
    5.10〜6.18の共通カーネルが並行してサポートされ、以前のプラットフォーム向けのカーネル(例:android14-6.1)を新しいAndroid端末の発売やアップグレードに使える
  6. TcpMaxConnectRetransmissions Microsoft
    以前のWindowsのデフォルト:SYN再送は2回、最初の待ち時間3秒から2倍ずつ、最後の再送の後さらに2倍の時間を待ってあきらめる(3+6+12=21秒)
  7. TCP/IP connectivity issues troubleshooting Microsoft
    SYN再送の回数はOSによって異なり、netsh int tcp show globalのMax SYN Retransmissionsで確認
  8. listen(2) — Linux manual page Linux man-pages
    listenのbacklog引数はsomaxconnで切り詰められる(Linux 5.4からデフォルト4096、それ以前は128)
  9. SNMP counter Linux kernel
    acceptキューが満杯になるとSYNを破棄し、TcpExtListenOverflows・TcpExtListenDropsがそろって増える、TcpExtTCPSynRetrans
  10. net/ipv4/tcp_input.c Linux kernel
    「Possible SYN flooding on port …」というログメッセージ
  11. net/ipv4/tcp_diag.c Linux kernel
    待ち受けソケットでは、ssのRecv-Qはacceptを待っている接続数、Send-Qはbacklogの上限

あわせて読みたい原因

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

同じ症状(接続不可・無限ロード)を起こすほかの層の原因

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