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

遊戲 Lag 白皮書 › TCP 重傳的根本原因

連線途中 NAT 或負載平衡器的 mapping 過期 NAT / load balancer mapping expired mid-connection

原因 ID rt-mapping · 主要負責 遊戲開發團隊(用戶端開發) · 協同 遊戲開發團隊(伺服器開發), 基礎設施團隊(網路基礎設施), 基礎設施團隊(伺服器基礎設施)

在含圖解與實驗的完整版中開啟卡片 →

中途設備刪除閒置連線的 mapping(記錄這條連線要轉送到哪裡的項目)後,接下來送出的封包就無法送達。連線會不斷重傳直到斷線,或是設備回傳拒絕連線(RST)而立刻斷線。

為什麼 有一段時間沒有任何封包往來的連線(暫離、大廳) → 於是 分享器 NAT、電信業者 CGNAT、防火牆、負載平衡器、雲端安全群組刪除閒置的 mapping → 畫面上 再次移動的瞬間接連重傳,最後斷線,或是直接斷線

症狀
斷線, 定格
因素
遺失
誰會遇到
只有我, 特定地區/電信業者
何時
閒置一段時間後
負責單位
主要負責 遊戲開發團隊(用戶端開發) · 協同 遊戲開發團隊(伺服器開發), 基礎設施團隊(網路基礎設施), 基礎設施團隊(伺服器基礎設施)
遊戲開發團隊要做的事
用戶端:以最短閒置逾時的一半以下為間隔送出心跳封包(玩家分享器與電信業者 CGNAT 的 mapping 只有從內部送出的封包才能確實更新,逾時時間我方也無法更改,所以由用戶端送出)、斷線時自動重新連線。伺服器:回應心跳封包,一段時間沒收到就主動先清掉連線(縮短 TCP keepalive 間隔(TCP_KEEPIDLE 等 socket 選項)、用 TCP_USER_TIMEOUT 快速偵測)、用 session token 接續連線。
基礎設施團隊要做的事
網路:彙整路徑上防火牆與負載平衡器的閒置逾時並提供給遊戲開發團隊,我方的防火牆與負載平衡器視需要調長。伺服器設備/OS:確認雲端安全群組的連線追蹤時間並提供給遊戲開發團隊。
數值參考
TCP mapping 的保留時間依設備而異,從幾分鐘到幾小時都有。雲端安全群組設為追蹤連線時,AWS Nitro v6 執行個體類型預設在 350 秒後刪除追蹤項目(其他類型為 5 天,請參考「雲端安全群組的連線追蹤過期」)。Linux TCP keepalive 的預設值是「閒置 2 小時才確認」,比大多數設備都晚。
圖表上
連線同時大量中斷 · 斷線次數、斷線前的閒置時間
查看位置
用伺服器端的封包擷取查看斷線連線的最後幾分鐘,仍存活的連線則用 ss -ti 的 lastsnd、lastrcv(距離最後一次傳送、接收經過的 ms)查看閒置時間。同時查看 nstat 的 TcpExtTCPAbortOnTimeout(計時器到期而放棄連線的次數)
符合的跡象
每條斷線的連線在斷線前的閒置時間都超過相近的值(路徑上設備的閒置逾時,例:AWS Nitro v6 執行個體安全群組的 350 秒),閒置後從第一個封包起就只有重傳、沒有 ACK,最後放棄,或是立刻收到 RST
不符合的跡象
與閒置時間無關、遊戲進行中也會斷線時,是其他原因(「路由變更、ECMP 不良路徑」、「防火牆與連線追蹤丟棄封包」)。心跳封包以最短閒置逾時的一半以下為間隔往來的連線,可排除這個原因
確認方式
用基礎設施工具確認(不需要遊戲程式碼)

出處

  1. RFC 5382: NAT Behavioral Requirements for TCP IETF
    建議 TCP NAT 的已建立連線閒置逾時應在 2 小時 4 分鐘以上(前提是設備可能會先刪除閒置的 session)
  2. RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP IETF
    NAT mapping 必須由內部送出的封包更新(REQ-6),由外部進來的封包更新則為選用(以 UDP 為準)
  3. Amazon EC2 security group connection tracking AWS
    TCP 閒置追蹤逾時的預設值,Nitro v6 執行個體類型為 350 秒,其他類型為 432,000 秒(5 天)。建議以短於 5 分鐘的間隔送 keepalive
  4. IP Sysctl Linux kernel
    tcp_keepalive_time 預設 2 小時
  5. tcp(7) — Linux manual page Linux man-pages
    TCP_KEEPIDLE(開始 keepalive 前的閒置時間)、TCP_USER_TIMEOUT(等待未確認的資料多久後關閉連線)
  6. RFC 5482: TCP User Timeout Option IETF
    TCP 使用者逾時:送出的資料在未獲確認的狀態下經過多久就關閉連線
  7. ss(8) — Linux manual page iproute2
    ss -i 的 lastsnd、lastrcv:距離最後一次傳送與接收所經過的時間(ms)
  8. SNMP counter Linux kernel
    TcpExtTCPAbortOnTimeout:TCP 計時器到期,沒有送出 RST 就放棄連線的次數

相關原因

同一層:TCP 重傳的根本原因

同一症狀(斷線)在其他層的原因

查看含圖解與實驗的完整版卡片