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

遊戲 Lag 白皮書 › L8 Socket 與協定

慢速用戶端造成的阻塞式傳送 Blocking send on a full socket

原因 ID sk-block-send · 主要負責 遊戲開發團隊(伺服器開發)

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

線路很慢的某位玩家傳送緩衝區已滿時,若用阻塞方式(緩衝區有空間之前呼叫不會返回的傳送)送出,伺服器執行緒就會一直等那一個人。

為什麼 慢速用戶端的傳送緩衝區已滿 → 於是 由於是阻塞式傳送,伺服器執行緒會等到緩衝區有空間為止 → 畫面上 該執行緒負責的所有人都出現定格、慢動作

症狀
定格, 慢動作
因素
停滯
誰會遇到
特定地點/頻道, 整個伺服器
何時
偶爾隨機發生, 人潮湧入時
負責單位
主要負責 遊戲開發團隊(伺服器開發)
遊戲開發團隊要做的事
改用非阻塞式傳送、為每個用戶端設定傳送佇列上限、丟棄過時的狀態更新。
圖表上
偶爾隨機飆高 · 伺服器 tick 時間、每條連線的 Send-Q
查看位置
用 ss -tn 找出 Send-Q(尚未收到 ACK 或尚未送出的位元組)已塞滿傳送緩衝區的連線,並在 tick 飆高的當下看遊戲伺服器的 thread dump(堆疊)中是否有停在 send 呼叫的執行緒
符合的跡象
有 Send-Q 塞滿的慢速連線時,負責該連線的執行緒停在 send,且只有同一執行緒負責的玩家一起停住
不符合的跡象
停住的執行緒在 send 以外的地方(鎖、DB 呼叫)等待時是「鎖競爭」、「遊戲執行緒上的同步呼叫」
確認方式
用基礎設施工具確認(不需要遊戲程式碼)

出處

  1. send(2) — Linux manual page Linux man-pages
    傳送緩衝區沒有空間時 send() 會阻塞,非阻塞模式下則立刻以 EAGAIN 返回
  2. send function (winsock2.h) Microsoft
    Winsock 在緩衝區空間不足時,除非是非阻塞模式,send 也會阻塞
  3. net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel
    ss 的 Recv-Q、Send-Q 值:listen socket 是等待 accept 的連線數與 backlog 上限;已連線的 socket 是應用程式尚未讀取的位元組數與尚未收到 ACK 的已送出位元組數

相關原因

同一層:L8 Socket 與協定

同一症狀(定格)在其他層的原因

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