# 遊戲 Lag 白皮書 (Game Lag White Paper) > 本白皮書將線上遊戲出現 lag(卡頓、瞬移、拉回、快轉、輸入延遲、定格、斷線等)的 228 個原因,從玩家畫面到伺服器資料庫,分成 13 層與 3 個主題(同步設計、只有部分人遇到的問題、TCP 重傳)來說明。雖以 MMO 案例為主,大部分內容與遊戲類型無關,適用於各類線上遊戲。每個原因都包含「為什麼 → 於是 → 畫面上」三個步驟、相關症狀、數值參考、負責解決的團隊(遊戲開發團隊、基礎設施團隊、外部)與各團隊要做的事、圖表形狀與確認方式,以及可信的出處(RFC,kernel、OS、雲端、引擎、DB 官方文件,論文)。 原因以 ID(例:mem-gc)指稱,每個原因都有獨立頁面(例:https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-gc.html)。數值為一般服務環境的代表值,預設值與版本的根據都列在各原因頁面的出處中。引用時請使用原因頁面的網址。MIT 授權。原文為韓文,本版為翻譯:https://jungrok5.github.io/mmo-lag-anatomy/ ## 文件 - [完整內容(Markdown)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/llms-full.txt): 原因、症狀、負責團隊、術語、出處全部收在一個檔案 - [純文字版](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/text.html): 不需要 JavaScript、在一頁讀完相同內容的 HTML - [遊戲 Lag 白皮書](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/): 含圖解與可親手操作實驗的完整版 ## 各症狀的原因 - [卡頓](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/stutter.html): 60 個原因。動作不流暢,不斷短暫停住又繼續動。 - [瞬移](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/teleport.html): 47 個原因。角色沒有移動過程,一下子就出現在很遠的位置。 - [拉回](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/rubber.html): 14 個原因。自己的角色往前走到一半,被拉回剛剛經過的位置。 - [快轉](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/burst.html): 36 個原因。停住的畫面重新動起來時,積壓的移動、打擊和傷害一口氣快速跑完。 - [慢動作](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/slowmo.html): 24 個原因。所有東西都變慢,技能施放和怪物移動看起來像被拉長。依伺服器設計不同,也可能速度不變,改以卡頓或瞬移的形式出現。 - [輸入延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/delay.html): 76 個原因。按下去之後要等一段時間才看到結果。畫面本身可能很流暢。 - [定格](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/freeze.html): 67 個原因。畫面裡所有東西停住一下(0.5 秒到數秒),然後又開始動。 - [吃指令/回檔](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/dropped.html): 36 個原因。明明做了的動作變成沒發生過,或是結果過了好一陣子才被推翻。 - [斷線](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/disconnect.html): 51 個原因。遊戲中連線中斷,被送回登入畫面或重新連線視窗。 - [連不上/無限讀取](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/noconnect.html): 45 個原因。進不了遊戲,或是停在讀取、進場畫面。 - [看不見/幽靈物件](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/s/invisible.html): 20 個原因。應該存在的 NPC、怪物、玩家只在自己的畫面上消失,或是早已消失的物件只留在自己的畫面上。 ## L1 用戶端遊戲程式 - [畫格時間尖峰](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-hitch.html): 某一個畫格的計算時間比平常多出好幾倍,畫面短暫停住。 - [用戶端垃圾回收](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-gc.html): 回收用過即丟的記憶體(垃圾)期間,整個遊戲會暫停。特徵是以規律的間隔出現卡頓。 - [主執行緒同步載入、著色器編譯](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-sync-load.html): 要繪製第一次出現的地圖、怪物、特效之前,得先讀取檔案並建立著色器,畫面因此停住。 - [儲存裝置太慢,資源串流跟不上](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-asset-stream.html): 在 HDD 這類較慢的儲存裝置上,讀取開放世界貼圖與模型的速度跟不上移動,物件會晚出現,或遊戲為了等待讀取而卡頓。 - [大量角色同畫面的渲染負載](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-crowd.html): 攻城戰、世界王這類數百人擠進同一個畫面的場合,光是繪製的成本就負荷不了。 - [主執行緒封包處理瓶頸](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-net-mainthread.html): 每個畫格只處理固定數量的已接收封包時,一次湧入的封包會不斷延到下一個畫格。 - [沒有內插緩衝或緩衝太短](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-no-buffer.html): 一收到伺服器封包就立刻繪製時,抖動(封包抵達間隔忽長忽短)會原封不動地出現在畫面上。 - [過度外插(dead reckoning)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-extrap.html): 封包沒來的期間,照最後的速度繼續顯示移動,等發現猜錯再拉回來。 - [用戶端預測不一致](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-predict.html): 自己的用戶端已經先顯示移動,伺服器卻算出不同的結果時,自己的角色就會被拉回去。 - [固定時間步長追趕失控](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-fixed-step.html): 停過一次之後集中補算落後的部分,又因為這些計算而再度落後。 - [時鐘同步誤差](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-clock.html): 用戶端推估的伺服器時間不準時,內插時間點與冷卻判定就會出現偏差。 - [float 時間精度損失](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-float-time.html): 以精度較低的浮點數格式(float)保存遊戲時間時,開著的時間越久,時間解析度(能分辨的最小時間差)就越差,動作與特效會顫動。 - [垂直同步(V-Sync)與渲染佇列](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-vsync.html): GPU 畫好的畫格會先在佇列裡堆上幾張,再配合螢幕的更新週期送出,這段期間輸入就被延遲。 - [用戶端記憶體洩漏](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-leak.html): 開得越久,記憶體用量越大,遊戲越來越慢,最後被強制關閉。 - [用戶端閃退](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-crash.html): 遊戲因未處理的錯誤而關閉。在玩家看來像斷線,但伺服器是正常的。 - [遊戲安全模組(反作弊)檢查](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/cg-anticheat.html): 為了防範外掛而與遊戲一起執行的安全模組會定期檢查。檢查太重,或與安全伺服器往來的心跳封包(定期確認連線存活的訊號)延遲時,就會卡頓或斷線。 ## L2 用戶端 OS 與裝置 - [背景處理程序占用 CPU](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-background.html): 防毒掃描、Windows Update、直播軟體、瀏覽器影片占住 CPU 核心時,遊戲執行緒分配不到 CPU,只能等待。 - [省電模式、過熱降頻](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-power.html): 筆電的電池模式、手機的省電模式、裝置過熱,都會讓 CPU、GPU 速度下降。過熱的特徵是一開始正常,過了一段時間才變慢。 - [計時器解析度](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-timer.html): Windows 的預設計時器以 15.6ms 為單位,所以「只休息 1ms」實際上會等到下一個計時器週期,最長拉長到 15.6ms。 - [手機 App 切到背景](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-mobile-bg.html): 為了看通知而把 App 暫時切到背景時,OS 會在幾秒後暫停(suspend)App,這段期間伺服器就會切斷玩家的連線。 - [Wi-Fi ↔ LTE/5G 切換](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-netswitch.html): 走出家門時 Wi-Fi 斷掉、改用 LTE/5G,自己的 IP 位址會改變,原本的連線就此失效。 - [安全軟體的封包檢查](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-security.html): 防毒軟體、防火牆檢查每一個封包時延遲會增加,太過頭還會把遊戲誤判為攻擊而封鎖。 - [接收緩衝區溢位](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-rcvbuf.html): 遊戲太忙,太晚從 socket(OS 提供的網路收送介面)取出封包時,OS 緩衝區就會溢位。 - [用戶端記憶體不足、swap](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-swap.html): 同時開著數十個瀏覽器分頁和遊戲時,OS 會把遊戲的一部分記憶體移到磁碟上。 - [顯示記憶體(VRAM)不足](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-vram.html): 畫質選項需要的記憶體比顯示卡記憶體還大時,OS 會把貼圖移到電腦的主記憶體再搬回來,因此出現卡頓。 - [Wi-Fi 背景掃描](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-wifi-scan.html): OS 為了尋找周圍的 Wi-Fi,會定期切換到其他頻道,這段期間通訊會短暫停止。 - [網路卡省電、驅動程式問題](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-driver.html): 有線網路卡或 Wi-Fi 晶片在封包與封包之間進入省電狀態時,要重新喚醒需要時間。 - [同一台裝置上的其他 App 占用頻寬](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-other-apps.html): 雲端同步、大型下載、遊戲更新在同一台電腦上執行時,遊戲封包得在佇列中等待。 - [視窗最小化或非作用中時的處理限制](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-unfocused.html): 切到其他視窗或把遊戲最小化時,遊戲與 Windows 會為了省電讓遊戲跑得比較慢。回到遊戲時,累積的封包會一口氣湧入,或者早已斷線。 - [overlay 程式干擾](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-overlay.html): 通訊軟體、啟動器、錄影、FPS 顯示程式為了在遊戲畫面上疊加自己的 UI,會介入遊戲的渲染流程(hook)。每個畫格的工作量因此增加,偶爾還會與遊戲衝突,造成頓一下或遊戲被強制關閉。 - [顯示器、輸入裝置與畫格生成的延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/co-display-input.html): ping 正常、操作卻很沉重時,可能是電視的影像處理、無線控制器或畫格生成功能在輸入與畫面之間增加了延遲。 ## L3 家用網路 - [Wi-Fi 干擾與訊號減弱](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-wifi.html): 訊號弱或有干擾時,無線區段要反覆重送好幾次,封包抵達的時間就會忽快忽慢。 - [Wi-Fi 頻道壅塞](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-channel.html): 在公寓大樓這類有數十台分享器的地方,大家共用同一個頻道,只能等待傳送機會。 - [Bufferbloat(分享器佇列)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-bufferbloat.html): 家人上傳影片或下載大型檔案時,分享器佇列會堆積相當於數百 ms 的封包,遊戲封包也得排在後面等待。 - [NAT mapping 過期](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-nat.html): 分享器會把一段時間沒有封包往來的閒置連線從 NAT 表中刪除。這是閒置一段時間後一有動作就斷線的常見原因。 - [分享器效能不足、過熱](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-router.html): 便宜的分享器同時接了數十台裝置、數千條連線時,分享器本身就處理不過來。 - [基地台換手(移動中)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-handover.html): 搭公車、捷運移動時,切換基地台的期間通訊會中斷。 - [RRC 狀態切換延遲(行動網路無線省電)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-rrc.html): 手機一段時間沒有通訊時,會把無線連線降到低耗電狀態,下一個封包要送出時得重新拉高,因此變慢。 - [行動網路訊號弱、收訊死角](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-weak-cell.html): 在電梯、地下室、建築物深處,重傳會增加、速度下降,最後斷線。 - [5G↔LTE 頻繁切換(5G 涵蓋邊緣)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-5g-flip.html): 在 5G 訊號弱的建築物內或 5G 涵蓋邊緣,手機會頻繁在 5G 與 LTE 之間切換,每次切換 ping 都會飆高或通訊短暫中斷。 - [公共 Wi-Fi/公司網路限制](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/hn-captive.html): 咖啡廳 Wi-Fi 的登入頁面或公司防火牆會擋掉遊戲連線。 ## L4 網際網路線路 - [傳播延遲(物理距離)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-distance.html): 光在光纖中 1 秒也只能前進約 20 萬 km。伺服器在遠方,效能再好也會慢。 - [衛星網路(低軌/同步軌道)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-satellite.html): 衛星網路的電波必須往返太空。同步軌道衛星光是往返就超過 0.5 秒;Starlink 這類低軌衛星平時很快,但在重新分配路徑的瞬間延遲會忽高忽低,有時還會短暫中斷。 - [繞遠路的路由](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-routing.html): 受電信業者之間互連合約的影響,連到附近的伺服器也可能繞到遠處再回來。 - [尖峰時段 peering 區段壅塞](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-peak.html): 晚上 9~11 點左右影音流量暴增,電信業者之間的互連區段(peering)容易壅塞。 - [海底電纜/國際線路故障](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-cable.html): 海底電纜一旦斷裂,修復前的幾週(長則幾個月)流量都得繞遠路,剩下的線路也會壅塞。 - [BGP 路由變更與收斂](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-bgp.html): 網際網路的路由資訊改變後重新收斂的幾秒到幾十秒(偶爾幾分鐘)之間,封包會遺失。 - [ECMP 其中一條路徑異常](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-ecmp.html): 電信業者與資料中心會為同一個目的地準備多條路徑,並替每條連線指定其中一條傳送。只要其中一條路徑故障,被分配到那條路徑的人就會持續遇到 lag。 - [電信業者限速與流量管理](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-shaping.html): 在用量超過上限或會管理特定流量的資費方案中,封包會被延後或丟棄。 - [國家/電信業者層級的 UDP 限制與封包檢測](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-udp-block.html): 部分網路會封鎖特定 UDP 位址與 port,或限制 UDP 速度;封包檢測設備也會過濾掉無法辨識的協定。用 UDP 通訊的遊戲在這類網路上會連不上或經常斷線。 - [線路品質不良](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-line.html): 接頭接觸不良、老舊線路或數據機異常,會造成持續的封包遺失與週期性的線路中斷。 - [DNS 故障與延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-dns.html): 負責把伺服器名稱轉成位址的 DNS 一旦變慢或失敗,就找不到登入伺服器與更新伺服器。 - [DDoS 造成共用線路飽和](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-ddos-path.html): 針對遊戲公司,或同一網路上其他對象的大量攻擊,會塞滿共用的線路。 - [電信業者共用 IP(CGNAT)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-cgnat.html): 行動網路與部分電信業者讓多位用戶共用一個 IP,並在短時間內清除閒置連線的 NAT mapping。 - [經由 VPN/遊戲加速器](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/isp-vpn.html): 開啟 VPN 或遊戲加速器後,封包會經過該公司的中繼伺服器。中繼伺服器很遠或壅塞時,反而會變慢。 ## L5 資料中心網路設備 - [防火牆 session 表飽和](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-firewall.html): 防火牆會把放行的每條連線記錄在 session 表中追蹤。表一旦滿了,就無法接受新連線。 - [DDoS 防護導流與誤判](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-ddos.html): 為了擋下攻擊而把流量導向清洗中心時,路徑會變長,有時還會把正常使用者誤判為攻擊而封鎖。 - [負載平衡器閒置逾時](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-lb-idle.html): 負載平衡器會在一段時間後清除閒置連線。遊戲還以為連線仍然維持著,結果就斷線了。 - [雲端安全群組的連線追蹤過期](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-cloud-conntrack.html): 雲端伺服器上的防火牆(安全群組)也會追蹤連線,閒置連線的追蹤項目會在一定時間後過期。即使是沒有經過負載平衡器、直接連線的伺服器,靜止不動的玩家也可能斷線。 - [雲端 NAT 閘道的連線與 port 上限](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-nat-gateway.html): 私有子網路中的伺服器對外(平台驗證、付款、外部 API)的連線,由 NAT 閘道轉換位址與 port 後送出。送往同一目的地的同時連線超過閘道的 port 上限時,新連線就會失敗。 - [負載平衡器分配不均與健康檢查誤判](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-lb-imbalance.html): 連線全集中到一台伺服器,或持續把人送往已經掛掉的伺服器。 - [交換器 microburst](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-microburst.html): 多台伺服器在同一瞬間同時對數千人送出封包時,這些流量匯集的交換器 port 上的小緩衝區,不到 1ms 就會滿溢。 - [資料中心線路飽和](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-uplink.html): 更新檔發布、log 傳送、備份與遊戲共用同一條線路時,線路會被塞滿。 - [網路設備容錯移轉(failover)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-failover.html): 路由器或防火牆有一台故障、切換到備援設備(failover)的幾秒之間,所有人的畫面都會停住。 - [纜線不良與 port 錯誤](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-bad-cable.html): 光模組或纜線不良時,經過該路徑的封包會有一定比例損毀。 - [MTU 不一致(只有大封包消失)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dc-mtu.html): 中途區段的 MTU(一次能傳送的大小)變小,而大小超過的通知又被擋掉時,只有大封包會一直消失。 ## L6 伺服器網路卡 - [NIC 中斷集中在單一核心](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-irq.html): NIC 只把封包到達的中斷(interrupt)送給一個 CPU 核心時,那個核心就會成為瓶頸。 - [Ring buffer 不足](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-ring.html): NIC 暫存封包的 ring buffer 太小時,封包瞬間湧入就會讓緩衝區滿溢而被丟棄。 - [中斷合併過度](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-coalesce.html): 為了減輕 CPU 負擔,NIC 把封包累積起來再一次通知 CPU(中斷合併,interrupt coalescing)時,累積多久就會晚多久。 - [超過雲端 PPS 上限](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-cloud-pps.html): 雲端伺服器依類型各有每秒封包數與頻寬的上限,超過時會默默丟棄。 - [NIC 頻寬飽和](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-saturate.html): 把 1Gbps、10Gbps 網路卡用到極限時,傳送佇列會變長,最後封包被丟棄。 - [虛擬化額外開銷與 noisy neighbor](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-noisy.html): 同一台實體伺服器上的其他虛擬機器大量使用網路或 CPU 時,自己伺服器的處理會不規則地被延後。 - [雲端主機維護與即時遷移](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-host-maintenance.html): 雲端供應商維護實體伺服器(主機)時,會把虛擬機器搬到其他主機(即時遷移),或暫時停住。這段期間整台伺服器都會停住,停住的時間一長,連線就會中斷。 - [NIC 驅動程式/韌體問題](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-reset.html): 驅動程式 bug 或功能異常讓網路卡停住並重新啟動,這段期間所有收發都會中斷。 - [GRO/LRO 合併等待延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/nic-offload.html): 這是把多個封包合併成一個來減輕 CPU 負擔的功能。依設定不同,小型遊戲封包有時會短暫等待下一個可以一起合併的封包。 ## L7 伺服器 OS(kernel) - [連線等待佇列(backlog)溢位](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-backlog.html): 維護剛結束時數萬人同時連線,kernel 的連線等待佇列(backlog)會溢位,連線請求因此被丟棄。 - [檔案描述子上限](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-fd.html): 每個連線都需要一個檔案描述子(fd,OS 為開啟的檔案或 socket 指定的編號),而一個處理程序能開啟的 fd 數量有上限。 - [Kernel socket 緩衝區不足](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-sockbuf.html): 傳送與接收緩衝區太小時,一遇到突發流量,UDP 收到的封包就會被丟棄,TCP 則因緩衝區沒有空間而無法傳送。 - [執行緒過多與 context switch](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-context.html): 執行緒數量遠多於 CPU 核心時,OS 會把 CPU 花在輪流切換執行緒上。 - [CPU steal(虛擬機器)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-steal.html): 實體伺服器(hypervisor)把虛擬機器的 CPU 時間暫時讓給其他虛擬機器(CPU steal)時,遊戲伺服器會停住。 - [容器 CPU 節流(CFS 配額)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-cpu-quota.html): 容器設了 CPU 上限時,只要在固定週期(通常是 100ms)內用完配額,剩下的時間就會被強制暫停(節流)。 - [伺服器電源管理(C-state、頻率調整)造成延遲飆高](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-cstate.html): 閒置的 CPU 核心為了省電,會進入深層省電狀態(C-state)並降低頻率。封包或計時器到來時,喚醒核心並拉高頻率需要時間,處理小封包時就會多出延遲。 - [OOM killer](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-oom.html): Linux 在記憶體耗盡時,會挑出使用最多記憶體的處理程序強制終止,通常就是遊戲伺服器。 - [記憶體回收與壓縮(compaction)造成的暫停](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-reclaim.html): OS 為了組出大分頁(huge page)而壓縮記憶體,或回收可用記憶體時,處理程序會停住。 - [系統時鐘跳動(NTP step)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-timejump.html): 伺服器時鐘一次被往前或往後調整幾秒時,依賴系統時鐘的計時器會同時觸發或停住。 - [排程工作](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-cron.html): 每天固定時間執行的 log 壓縮、備份、安全掃描會占用 CPU 與磁碟。 - [OS、kernel、驅動程式、韌體更新後的效能變化](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-os-update.html): 遊戲程式碼沒變,但伺服器 OS、kernel、驅動程式、韌體更新後就變慢。更新有時會改變預設值、排程器、CPU 漏洞緩解措施(mitigations)與驅動程式的行為。 - [伺服器 conntrack 表飽和](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-conntrack.html): Linux 防火牆會把每條連線記錄在連線追蹤(conntrack)表中,這個表碰到上限時就會丟棄新封包。 - [伺服器間連線的臨時 port 耗盡](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/so-ports.html): 遊戲伺服器頻繁地對 DB 或其他伺服器建立又關閉短連線時,已關閉的連線會占用 port 一段時間,導致無法開啟新連線。 ## L8 Socket 與協定 - [TCP HOL 阻塞](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-hol.html): TCP 為了維持順序,在重新收到遺失的那一個封包之前,不會把之後到達的封包交給遊戲。 - [TCP RTO 與指數退避](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-rto.html): 每次重傳又失敗,等待時間就加倍,於是線路短暫中斷會變成長時間停住。 - [Nagle 演算法 + 延遲 ACK](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-nagle.html): 把小封包集中起來送的 Nagle 演算法,與延後送出 ACK 的延遲 ACK 互相牽制,每次把訊息分段寫入就會延遲 40~200ms。 - [慢速用戶端造成的阻塞式傳送](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-block-send.html): 線路很慢的某位玩家傳送緩衝區已滿時,若用阻塞方式(緩衝區有空間之前呼叫不會返回的傳送)送出,伺服器執行緒就會一直等那一個人。 - [慢速用戶端(slow consumer)的處理策略](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-slow-client.html): 對於待傳送資料不斷累積的用戶端,伺服器會丟棄過時的狀態更新,或直接切斷連線。 - [keepalive 預設值 2 小時](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-keepalive.html): 對方沒有送出關閉訊號就消失時,TCP 要過很久才會察覺。keepalive(確認閒置連線是否仍存活的 TCP 功能)預設是關閉的,即使開啟,也要閒置 2 小時才開始確認。 - [UDP 封包的 IP 分段](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-fragment.html): 超過 MTU(一次能傳送的最大大小)的 UDP 封包會在 IP 層被分段(fragmentation),只要遺失其中一個分段,整個封包就會被丟棄。 - [可靠 UDP 的重傳設定](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-reliable-udp.html): 在 UDP 上自行實作的重傳規則太保守時復原會變慢,太積極時反而讓線路更壅塞。 - [閒置後的慢啟動(slow start)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-slowstart.html): 連線閒置一段時間後,TCP 會再次縮小壅塞視窗(一次能送出的量),所以突然要送大量資料時,得分成好幾次送出。 - [壅塞控制造成傳送量驟降](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-congestion.html): TCP 把封包遺失視為壅塞的訊號,會把傳送速率降低 30~50%。對 Wi-Fi 造成的遺失也會做出同樣的反應。 - [RST 強制關閉造成最後的資料遺失](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-linger.html): 伺服器倉促切斷連線時,最後送出的通知或存檔完成訊號會消失。 - [阻塞式 I/O 架構](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-blocking-io.html): 執行緒在等待某個 socket 時無法做其他事的架構,玩家越多整體就越慢。 - [SO_REUSEPORT 分配不均](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-reuseport.html): 多個處理程序共用同一個 port 接收時,kernel 會依位址雜湊為每個連線指定負責的處理程序,之後不再更換。其中一個處理程序停住時,只有分配給它的人要等待。 - [Windows UDP socket 的 WSAECONNRESET 錯誤](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sk-udp-connreset.html): Windows 伺服器向已經離開的用戶端送出 UDP 時,會收到「port 無法到達」(ICMP)的通知。這個通知會讓下一次接收呼叫以錯誤結束;如果伺服器程式碼把這個錯誤當成 socket 本身故障來處理,所有使用該 socket 的人都會受到影響。 ## L9 伺服器遊戲程式 - [超出 tick 預算](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-tick-overrun.html): 一個 tick 內要做的事超出預算時,伺服器的 tick 週期會拉長,整個區域的遊戲進行變慢,或出現卡頓。 - [視野(AOI)計算量暴增(N²)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-aoi.html): 若要判斷誰能看到誰而讓所有人兩兩比較,人數變成 10 倍時,運算量會變成 100 倍。 - [廣播量暴增](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-broadcast.html): 把一個人的移動送給所有看得到他的人時,要送出的狀態更新數量會是聚集人數的平方。 - [單執行緒區域過載(熱點)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-hotzone.html): 在每個區域由一個執行緒負責的架構中,人潮擠到同一處時,只有那一個核心會到 100%。 - [鎖競爭](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-lock.html): 多個執行緒為了寫入同一份資料而等待同一個鎖時,執行緒再多也只能一次執行一個。 - [死結](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-deadlock.html): 兩個執行緒各自等待對方持有的鎖時,就會永遠停住。 - [遊戲執行緒上的同步呼叫](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-sync-call.html): 在 tick 進行中等待 DB 回應或檔案寫入時,伺服器上整個遊戲進行就會停住同樣長的時間。 - [訊息佇列積壓](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-queue.html): 請求進來的速度比處理速度快而在佇列中累積時,排在後面的請求要幾秒後才會處理,或被丟棄。 - [計時器集中同時觸發](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-timer-burst.html): 所有怪物重生、所有 buff 到期、整點獎勵都擠在同一個 tick 時,那一個 tick 的負擔會變成平常的數十倍。 - [尋路運算暴增](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-pathfinding.html): 數百隻怪物同時追擊玩家並計算路徑時,會耗用大量 CPU。 - [序列化與壓縮的成本](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-serialize.html): 把要送出的資料轉成位元組並壓縮也要耗用 CPU,人多時這項成本會暴增。 - [伺服器當機](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-crash.html): 伺服器處理程序因未處理的錯誤而終止時,該伺服器上所有人會同時斷線。 - [執行緒池耗盡](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-threadpool.html): 負責處理工作的工作執行緒全被慢的工作綁住時,新請求只能無止盡地等待。 - [無窮迴圈、邏輯失控](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-infinite-loop.html): 因 bug 導致一個 tick 結束不了時,伺服器就會停住,看門狗會強制重新啟動。 - [集中在單一目標的戰鬥(世界王)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-hot-entity.html): 數百人同時攻擊同一隻王時,這隻王的運算全集中在一處,打擊資訊也要傳送給所有看得到的人。 - [進入密集區域時的生成暴增](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-spawn-burst.html): 用傳送移動到擠滿人的城鎮時,伺服器必須一次送出數百位新進入視野者的外觀、裝備與狀態。 - [物件累積(未清理的道具、召喚物)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-entity-buildup.html): 該消失的地上道具、召喚物、已結束的計時器沒有清理而不斷累積時,伺服器開得越久,每個 tick 要做的事就越多。 - [更新改變了流量模式](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sp-patch-traffic.html): 新內容、特效、同步項目讓封包變大、變頻繁時,原本運作正常的伺服器在更新後就會碰到 MTU、頻寬、封包數上限。 ## L10 記憶體 - [伺服器 GC 全面暫停](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-gc.html): Java、C# 伺服器為了回收垃圾而暫停所有執行緒(stop-the-world)的期間,整個伺服器都會停住。 - [腳本引擎的 GC 暫停](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-script-gc.html): 即使是 C++ 伺服器,只要任務、AI、技能是用 Lua 等腳本執行,腳本引擎進行 GC 的期間,該 zone 就會停住。 - [記憶體配置暴增](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-alloc.html): 活動期間大量產生暫時物件時,GC 執行的頻率會比平常高出許多。 - [記憶體洩漏](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-leak.html): 沒有釋放的記憶體一點一點累積,幾天後演變成 GC 暴增、swap 或處理程序被強制終止。 - [GC thrashing(heap 可用空間不足)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-gc-thrash.html): 存活資料逼近 heap 上限時,每次 GC 幾乎回收不到東西,GC 就會不停反覆執行。 - [Swap](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-swap.html): 記憶體不足、OS 把部分內容移到磁碟後,每次用到那塊記憶體,都得等待慢上 1,000 倍以上的磁碟。 - [快取未命中](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-cache-miss.html): 資料散落在記憶體各處時,CPU 每次都必須到較慢的 RAM 讀取並等待資料。 - [記憶體碎片化](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-fragment.html): 反覆配置與釋放,讓閒置空間被切得零碎時,占用的記憶體會遠多於實際使用量。 - [NUMA 遠端記憶體](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/mem-numa.html): 在有兩顆 CPU 的伺服器上,使用接在另一顆 CPU 上的記憶體時,存取會變慢。 ## L11 磁碟 - [同步寫入 log](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-sync-log.html): 遊戲執行緒每寫一行 log 都要等磁碟寫完的話,磁碟一忙,遊戲進行也會跟著停住。 - [fsync 暴增](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-fsync.html): 要求把資料「確實」寫入磁碟時,依磁碟不同,每次需要 0.1ms~數十 ms;請求一多,佇列就會變長。 - [雲端磁碟 burst credit 耗盡](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-burst.html): 部分雲端磁碟與小規格伺服器有 burst credit(突發額度),可以短時間跑得比基準效能快;忙碌時段一拉長、額度用完,速度就會突然下降。 - [IOPS 上限與佇列飽和](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-iops.html): 請求數超過磁碟每秒能處理的數量時,佇列會變長,延遲急遽增加。 - [磁碟已滿](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-full.html): log 與 dump 越積越多、把磁碟塞滿時,寫入會失敗;沒有防範措施的話,伺服器會當機。 - [備份、壓縮、掃描作業](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-backup.html): 凌晨的備份、log 壓縮、安全掃描獨占磁碟時,遊戲伺服器的讀寫就會被擠到後面。 - [伺服器端的延遲載入](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-lazy-load.html): 伺服器在副本、地圖資料第一次被請求時才從磁碟讀取的話,那個 tick 期間所有人都會停住。 - [寫入 core dump](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-coredump.html): 伺服器當機時要把數 GB 的記憶體寫入磁碟,有時會讓重新啟動延後好幾分鐘。 - [HDD 尋軌延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/dk-hdd.html): HDD 的讀寫頭必須在碟片上移動(尋軌,seek),所以讀寫分散各處的資料時,每次要花將近 10ms。 ## L12 資料庫 - [沒有索引的查詢](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-no-index.html): 沒有索引時,要找出符合條件的資料列,就必須讀完整張資料表(全表掃描)。 - [熱點資料列鎖定競爭](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-hot-row.html): 所有人都要修改同一筆資料列(公會倉庫、拍賣場熱門道具、全伺服器共用的計數器)時,一次只有一個請求能取得鎖定。 - [DB 死結](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-deadlock.html): 兩個 transaction(當成一個整體處理的一組 DB 操作)互相等待對方鎖住的資料列時,DB 會強制取消其中一方。 - [連線池耗盡](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-pool.html): 與 DB 建立的連線數是固定的,慢查詢占住連線時,其餘請求只能等待。 - [複寫延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-replica-lag.html): 寫入走主 DB、讀取走複本的架構下,複本跟得慢時,剛寫入的內容就會看不到。 - [檢查點與 log flush](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-checkpoint.html): DB 定期把記憶體中的變更一次大量寫入磁碟的瞬間,查詢會變慢。 - [冷快取(剛重新啟動時)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-cold-cache.html): DB 重新啟動後記憶體快取是空的,有一段時間所有查詢都要從磁碟讀取。 - [登入暴增與 N+1 查詢](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-login-storm.html): 載入一個角色要分開查詢數十次的話,數萬人同時登入就會變成數百萬個查詢。 - [大量批次作業](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-batch.html): 在營運時段執行排行榜彙總、信件批次發送、舊資料清理時,會占用鎖定與磁碟。 - [DB 容錯移轉](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-failover.html): 主 DB 故障、切換到備援 DB 的期間無法寫入,最後一批還沒複寫過去的資料可能會遺失。 - [存檔週期過長造成的進度遺失](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-save-interval.html): 為了減輕負載而每隔幾分鐘才存檔一次的話,伺服器在兩次存檔之間當機時,進度就會消失。 - [Cache stampede](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-cache-stampede.html): 熱門資料的快取同時過期時,數千個請求會一口氣湧向 DB。 - [長時間未結束的 transaction](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-long-tx.html): 一個 transaction 長時間不結束時,會一直持有鎖定,DB 也無法清理(purge)舊版本的資料,整體會越來越慢。 - [Redis 慢指令](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-redis-block.html): Redis 一次只處理一個指令,因此一個慢指令就會擋住後面所有的請求。 - [執行計畫改變造成的查詢延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-plan-flip.html): 程式碼沒變,DB 卻改變了處理同一個查詢的方式(執行計畫)時,昨天只要 2ms 的查詢,今天會變成數百 ms。 - [營運中 schema 變更(DDL)的鎖定](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/db-ddl-lock.html): 在服務中替資料表新增欄位或索引時,可能因為一個只需要短暫持有的鎖定,讓所有使用該資料表的請求都在等待。 ## L13 伺服器架構與維運 - [經由閘道/proxy](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-gateway.html): 在用戶端與遊戲伺服器之間放一台中介伺服器時,每經過一次就多一段處理時間,而且這台伺服器會成為單點故障。 - [切換 zone(跨伺服器轉移)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-zone-transfer.html): 進入其他地圖或副本時,把角色資料交給另一台伺服器的過程中會產生延遲與失敗。 - [連鎖故障](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-cascade.html): 一個服務變慢時,呼叫它的伺服器會卡在等待回應,連不相關的功能也跟著停擺。 - [附屬伺服器故障](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-subservice.html): 聊天、隊伍、拍賣場這類與遊戲伺服器分開運作的伺服器故障時,只有那個功能無法運作。 - [部署與重新啟動](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-deploy.html): 為了更新而重新啟動伺服器時,如果不先把連線移走,原本在那台伺服器上的人就會斷線,關閉前的存檔與重新連線也會同時湧入。 - [自動擴展延遲](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-autoscale.html): 人潮湧入時會自動增加伺服器,但準備要花幾分鐘,這段期間既有的伺服器處於過載。 - [log 與監控過載](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-monitoring.html): 發生故障時 log 會暴增,以同步方式送出 log 的伺服器會因為 log 變得更慢。 - [伺服器之間的時鐘差異](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-clock-skew.html): 各伺服器的時鐘各差一點時,冷卻時間、buff、活動開始的判定就會在伺服器之間對不上。 - [巨集/機器人過多](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-bots.html): 機器人送出請求的頻率遠高於真人,會吃掉伺服器的處理量。 - [依賴外部服務](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-external.html): 平台登入、付款、身分驗證這類外部服務變慢或停擺時,會卡在那個步驟。 - [配對與區域分配錯誤](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-region-match.html): 沒被分到近的區域、卻被分到遠方區域的伺服器時,即使線路正常,也只有那位玩家的 ping 一直偏高。 - [TLS 憑證過期/設定錯誤](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-cert.html): 登入、API、更新伺服器的憑證過期或缺少中繼憑證時,從那一刻起新連線的用戶端 TLS 連線都會失敗。 - [登入排隊上限與重新連線寬限不足](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/in-login-queue.html): 上市或維護剛結束時連線湧入,登入排隊碰到上限就拒絕新的排隊,正在排隊的玩家只要短暫斷線就會失去位置,回到隊伍最後面。 ## 同步設計 - [伺服器回應後才演出(請求-回應方式)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-request-response.html): 按下按鈕後,在伺服器回應之前既沒有動畫也沒有音效。ping 直接就是反應速度。 - [依序往返過多的協定(chatty)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-chatty.html): 一次操作需要依序與伺服器往返好幾次時,ping 會乘上這個次數。 - [沒有技能預輸入](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-no-queue.html): 必須收到伺服器確認前一個技能已結束才能按下一個技能時,每次連段之間都會夾著一段往返時間。 - [被 ping 吃掉的短判定區間](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-short-window.html): 閃避、格擋、防禦這類需要反應的時間很短時,ping 會把這段時間吃掉,出現躲不掉的攻擊。 - [沒有延遲補償的判定](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-no-lagcomp.html): 伺服器只用「伺服器上現在的位置」判定命中時,判定會與自己看到的畫面不一致。 - [延遲補償過度](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-lagcomp-overreach.html): 以攻擊者為準回溯得太遠時,被打的一方明明已經躲好了還是會中彈。 - [用戶端權威](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-client-auth.html): 各自決定自己的結果時,自己的畫面很順暢,但結果會與其他人的畫面不一致,也容易被外掛利用。 - [Lockstep 中等待最慢的玩家](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-lockstep.html): 在所有人一起計算同一回合的架構中,只要一個人的輸入晚到,所有人都要等。 - [Rollback netcode 預測失敗](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-rollback.html): 先預測對手的輸入並呈現出來,猜錯時就回溯重新計算。ping 越大,回溯的幅度越大。 - [沒有時間戳記、一到就播放](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-no-timestamp.html): 伺服器事件沒有附上發生時間、一收到就播放時,網路抖動會讓演出時機跟著忽快忽慢。 - [雙重 tick 等待](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-double-tick.html): 請求先累積到下一個 tick 才處理,結果又等到再下一個 tick 才送出時,tick 間隔會被加上兩次。 - [過於嚴格的伺服器驗證](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-strict-check.html): 伺服器對移動速度、冷卻時間、射程檢查得太嚴格時,連因抖動而擠在一起抵達的正常輸入也會被拒絕。 - [主機(房主)架構](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-host.html): 由某個玩家的電腦擔任伺服器時,那個人的線路與電腦效能決定了所有人的體感。 - [先行演出後遭伺服器拒絕](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-optimistic-reject.html): 自己畫面上先呈現的打擊、技能,事後沒有被伺服器認可時,明明看到的結果就變成沒發生過。 - [指令同步的路徑計算不一致](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-path-mismatch.html): 只互傳「走到這裡」、路徑由兩邊各自計算時,計算只要有一點不同,角色或怪物就會走上不同的路徑,再被拉回原位。 - [快照傳送頻率太低](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/sy-low-send-rate.html): 伺服器每秒只送幾次位置更新(快照)時,內插緩衝就得相應拉長,看到的其他角色會是更久以前的狀態。 ## 只有部分人遇到的問題 - [慢的人在別人畫面上快轉移動](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-slow-burst.html): 線路差的人,輸入會忽快忽慢、成批抵達伺服器。伺服器每個 tick 收到多少就套用多少時,在其他人眼中,那個角色會頓一下後一次走好幾步。 - [一到就處理的伺服器造成快轉](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-event-server.html): 封包一抵達就立即處理並通知的伺服器,會把慢的人成批湧入的動作接連立即執行。 - [各玩家的輸入緩衝大小](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-input-buffer.html): 伺服器替每個人暫存一點輸入、每個 tick 取出一個使用時,在其他人眼中很流暢,但本人的動作在伺服器上確定的時間點也會晚上這麼多。 - [集中在特定電信業者玩家的驗證誤判](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-isp-validation.html): 線路抖動大的人,輸入會成批抵達,因此常被伺服器的速度、冷卻檢查攔下。 - [一個慢的隊友與王的機制](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-raid-member.html): 在所有人必須在指定瞬間一起反應的團隊副本機制中,一個慢的人反應太晚,就會讓整個隊伍失敗。 - [怪物控制權在慢速用戶端上](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-mob-control.html): 有些遊戲為了減輕伺服器負載,把怪物移動的計算交給附近某位玩家的用戶端。那個人線路差時,該怪物在所有人的畫面上都會動得很怪。 - [特定角色的資料過於龐大](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-heavy-char.html): 累積了數千個道具或信件,或好友、封鎖名單、buff 特別多的角色,在登入、儲存與通知周圍玩家時要處理的量是別人的好幾倍。與線路無關,只有用那個角色時才慢。 - [頻道、實例、相位不同](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-phase.html): 兩個角色在不同的頻道或實例(instance),或處在依任務進度決定能看到哪些 NPC 的不同「相位」時,看到的是不同的世界。 - [載入中抵達的出現通知被丟棄](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-loading-drop.html): 一進入 zone,伺服器就送出周圍 NPC 的出現通知,但用戶端還在載入地圖,於是把通知丟掉。 - [視野登錄順序錯亂](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-aoi-race.html): 角色登錄到視野格狀(grid)的瞬間,與 NPC 換到其他格子的瞬間重疊時,該 NPC 的出現通知可能會漏掉。 - [基準快照遺失](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-baseline.html): 在伺服器只送「與上次不同的部分」的方式中,最初送一次的完整資訊(基準)遺失時,之後的變化量就無法套用。 - [消失通知遺失(幽靈物件)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-ghost.html): 反過來,漏掉「已消失」的通知時,早已死亡或離開的 NPC、玩家會只留在自己的畫面上。 - [剛進場時湧入的出現資訊遺失](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-spawn-burst.html): 踏進 zone 的瞬間,伺服器會一次送出周圍數十~數百個物件的出現資訊。若用不可靠(unreliable)通道送出,或在載入中無法讀取 socket 的期間接收緩衝區溢位,就會有一部分消失且不再重送。 - [物件 ID 重複使用造成誤認](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-id-reuse.html): 死亡的 NPC 重新出現時,伺服器若再次使用同一個物件 ID,在這段期間漏掉消失通知的用戶端,就會把新的 NPC 誤認成舊的 NPC。 - [固定 UDP port 衝突](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-port-collision.html): 用戶端若設計成使用固定的本機 port,同一台電腦的第二個用戶端就無法使用該 port,或與第一個用戶端分食封包。 - [以 IP/裝置區分 session 的 bug](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-session-key.html): 伺服器或中介伺服器以 IP 或裝置 ID 區分連線時,會把同一台電腦(同一個公用 IP)的兩個用戶端視為同一個人。 - [多開限制](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-multiclient.html): 安全模組或伺服器政策限制同一台電腦開多個用戶端時,第二個用戶端會無法執行或連線,或者先開的那一個會斷線。有些遊戲只封鎖額外用戶端的功能。 - [背景視窗的處理限制](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-background.html): 背景視窗中的用戶端,會被遊戲、引擎、OS 降低畫格數與處理量。收到的封包來不及處理,就會積壓或溢位。 - [快取/資源檔案同時存取衝突](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-asset-lock.html): 兩個用戶端同時寫入同一個快取資料夾或鎖定檔案時,其中一邊會載入不了 NPC 模型或貼圖。 - [記憶體/VRAM 不足導致串流失敗](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-vram.html): 兩個用戶端分著用顯示記憶體時,沒有空間載入新需要的模型與貼圖,部分物件就畫不出來。 - [顯示選項不同](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-display-option.html): 顯示人數上限、隱藏 NPC 名字與模型、低規格模式這類選項,在兩個用戶端設定不同時,看到的東西就不同。 - [用戶端版本、資料不一致](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-version.html): 第二個用戶端是不同的安裝版本或尚未更新完成時,會不認得伺服器送來的新 NPC ID,直接默默忽略。 - [各連線的傳送預算與優先順序](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-priority.html): 伺服器對每條連線的傳送量設上限、從近的開始送時,上限被設得較低的那一邊,會較晚收到或收不到遠處的 NPC。 - [時鐘推估誤差導致物件暫緩顯示](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/pt-clock-hold.html): 用戶端推估的伺服器時間有誤時,會把剛抵達的物件資訊當成「還在未來」而暫緩,或當成「太舊」而丟棄。 ## TCP 重傳的根本原因 - [無線區段的封包遺失](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-wireless.html): Wi-Fi 與行動網路在無線區段會先重傳幾次,仍然失敗就丟棄封包。被丟棄的封包,TCP 要過好一段時間才會重送。 - [瓶頸佇列溢位(壅塞遺失)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-queue-drop.html): 分享器、電信業者之間的互連區段、資料中心線路這類最窄的地方,佇列一滿就會丟棄新進來的封包。 - [突發傳送造成淺緩衝區溢位](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-burst.html): 伺服器每個 tick 把數千人份的更新在一瞬間集中送出時,交換器的小緩衝區或雲端的瞬間上限不到 1ms 就會溢位,部分封包因此被丟棄。 - [Policer 丟棄超額流量](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-policer.html): 電信業者的資費方案、雲端執行個體的上限、DDoS 防護設備,有時會把超過規定速度的封包直接丟棄,不放進佇列。 - [實體層錯誤(線材、光模組、接頭不良)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-physical.html): 纜線損壞、沾了灰塵的光纖接頭、壽命將盡的光模組會造成位元錯誤,損壞的封包會被設備默默丟棄。 - [雙工模式不一致](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-duplex.html): 一端設為自動協商、另一端把速度與雙工固定時,其中一端會以半雙工運作,每當負載升高就因碰撞而遺失封包。 - [接收端伺服器主機丟棄封包](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-host-drop.html): 封包已經到了伺服器,卻因 NIC 的 ring buffer(暫存剛抵達封包的緩衝區)溢位,或 kernel 負責接收處理的 CPU 核心滿載而被丟棄。 - [防火牆與連線追蹤丟棄封包](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-stateful-fw.html): 防火牆或 Linux 連線追蹤(conntrack,把經過的連線記錄在表中的功能),在表已滿或判斷連線狀態不符時,會丟棄封包。 - [中間設備超過處理上限(防火牆、IPS、DDoS 防護)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-appliance-pps.html): 防火牆、入侵防禦設備(IPS)、DDoS 防護設備會逐一檢查經過的封包。從超過檢查能力的那一刻起,處理不了的封包就會被丟棄。 - [MTU 黑洞(只有大封包反覆遺失)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-mtu.html): 中途區段能接收的大小變小,而「封包太大」的通知(ICMP)又被擋掉時,大封包不管重送幾次都會一直消失。 - [連線途中 NAT 或負載平衡器的 mapping 過期](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-mapping.html): 中途設備刪除閒置連線的 mapping(記錄這條連線要轉送到哪裡的項目)後,接下來送出的封包就無法送達。連線會不斷重傳直到斷線,或是設備回傳拒絕連線(RST)而立刻斷線。 - [路由變更、ECMP 不良路徑](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-path.html): 網際網路路由變更的那幾秒內,或是多條 ECMP 路徑中被分配到不良路徑的連線,會有封包消失。 - [延遲飆升造成的不必要重傳](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-spurious-delay.html): 封包沒有消失,只是短暫地很晚才到;但這段延遲比 RTO 長時,傳送端就會判斷為遺失而重傳。 - [封包亂序造成的不必要快速重傳](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-reorder.html): 封包經過多條路徑或聚合鏈路時順序被打亂,接收端會以重複 ACK 告知「有封包缺漏」,傳送端就把其實已正常送達的封包再送一次。 - [ACK 延遲或消失(上傳飽和)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-ack-path.html): 資料已順利送達,但「收到了」的 ACK 在塞滿的上傳佇列裡延遲或消失時,傳送端會判斷為遺失而重傳。 - [RTO 設定不符合環境](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-rto-setting.html): RTO 最小值調得太低時,只要稍微延遲就會產生不必要的重傳;預設值(200ms)對遊戲來說又太長,每遺失一次就要停住很久。 - [thin stream 復原緩慢](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-thin.html): 像遊戲這樣零星送出小封包時,在湊齊「後續 3 個封包」之前 RTO 就先到了。同樣的遺失,停住的時間比大量傳輸長得多。 - [中間設備移除 TCP 選項](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-sack-stripped.html): 部分防火牆或加速設備刪除或改寫 TCP 選項時,遺失多個封包後一個往返只能復原一個,或是視窗(一次可送出的量)變小,傳輸因此變慢。 - [Zero window(看起來像重傳的停頓)](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-zero-window.html): 接收端程式沒有及時讀取 socket、緩衝區塞滿時,傳送端會停止傳送,只送出 zero window probe。線路本身沒有問題。 - [連線請求(SYN)重傳](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/c/rt-syn.html): 連線請求因連線等待佇列(backlog)溢位或被防火牆阻擋而消失時,用戶端 OS 會從 1 秒後開始,逐步拉長間隔重送。 ## 判定與案例 - [用觀測資料判定](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/#judge): 範圍 → 時間點 → 層級的判定流程、判定訊號表、13 種圖表形狀、數字的解讀方式(平均值與 p99) - [各情境處理流程](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/text.html#playbooks): 更新後 lag、新增海外國家與地區 - [實際事故案例](https://jungrok5.github.io/mmo-lag-anatomy/zh-tw/text.html#cases): 原開發商、營運商公開的事後檢討與相關原因 ## 其他語言 - [한국어 (Korean)](https://jungrok5.github.io/mmo-lag-anatomy/llms.txt) - [English](https://jungrok5.github.io/mmo-lag-anatomy/en/llms.txt) - [日本語 (Japanese)](https://jungrok5.github.io/mmo-lag-anatomy/ja/llms.txt) - [简体中文 (Chinese (Simplified))](https://jungrok5.github.io/mmo-lag-anatomy/zh-cn/llms.txt) - [Deutsch (German)](https://jungrok5.github.io/mmo-lag-anatomy/de/llms.txt) - [ไทย (Thai)](https://jungrok5.github.io/mmo-lag-anatomy/th/llms.txt) - [Tiếng Việt (Vietnamese)](https://jungrok5.github.io/mmo-lag-anatomy/vi/llms.txt) - [Русский (Russian)](https://jungrok5.github.io/mmo-lag-anatomy/ru/llms.txt) - [Português (Brasil) (Portuguese (Brazil))](https://jungrok5.github.io/mmo-lag-anatomy/pt-br/llms.txt) - [Español (Spanish)](https://jungrok5.github.io/mmo-lag-anatomy/es/llms.txt) - [Bahasa Indonesia (Indonesian)](https://jungrok5.github.io/mmo-lag-anatomy/id/llms.txt) ## Optional - [GitHub 儲存庫](https://github.com/jungrok5/mmo-lag-anatomy): 原始碼、資料格式、貢獻方式 - [作者:Jeongrok Oh](https://jungrok5.github.io/resume/en/): 履歷