遊戲 Lag 白皮書 › L7 伺服器 OS(kernel)
檔案描述子上限 File descriptor limit (ulimit)
原因 ID so-fd · 主要負責 基礎設施團隊(伺服器基礎設施) · 協同 遊戲開發團隊(伺服器開發)
在含圖解與實驗的完整版中開啟卡片 →
每個連線都需要一個檔案描述子(fd,OS 為開啟的檔案或 socket 指定的編號),而一個處理程序能開啟的 fd 數量有上限。
為什麼 同時上線人數達到處理程序的檔案描述子上限 → 於是 伺服器無法接受新連線(Too many open files),開啟 log 檔與 DB 連線也跟著失敗 → 畫面上 從某個固定人數起誰都進不來,出現連不上/無限讀取
- 症狀
- 連不上/無限讀取
- 因素
- 遺失
- 誰會遇到
- 整個伺服器
- 何時
- 剛登入/維護剛結束, 人潮湧入時
- 負責單位
- 主要負責 基礎設施團隊(伺服器基礎設施) · 協同 遊戲開發團隊(伺服器開發)
- 遊戲開發團隊要做的事
- 結束連線時確實關閉 socket(防止 fd 洩漏);accept 因 EMFILE(fd 不足)失敗時,暫停接受連線一段時間,或用事先保留的備用 fd 接受後立刻關閉(避免反覆處理同一個連線通知而浪費 CPU)。
- 基礎設施團隊要做的事
- 確認 ulimit 與服務設定(systemd 的 LimitNOFILE),接近上限時發出警示。
- 數值參考
- Linux 若沒有另外設定服務,上限仍常是 1,024。遊戲伺服器通常會調高到數萬~數十萬。Windows 沒有這麼低的預設上限。
- 圖表上
- 碰到上限後持平 · 處理程序開啟的 fd 數、同時上線人數
- 查看位置
- 用 pidstat -v 看遊戲伺服器處理程序的 fd-nr(開啟的檔案描述子數),用 /proc/PID/limits 看開啟檔案數上限,並在伺服器 log 中找 accept 失敗(EMFILE, Too many open files)
- 符合的跡象
- fd 數在上限值持平,從那個時間點起 accept 以 EMFILE 失敗
- 不符合的跡象
- fd 數遠低於上限就不是這個原因。連線請求在 kernel 被丟棄時是「連線等待佇列(backlog)溢位」;問題出在連線追蹤時是「伺服器 conntrack 表飽和」
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
- 深入了解
- 沒被接受的連線會一直留在 kernel 的連線等待佇列(backlog)裡,依伺服器程式碼的寫法,可能會不斷收到「有新連線」的通知而浪費 CPU。
出處
- systemd-system.conf(5) — Linux manual page systemd
服務的 DefaultLimitNOFILE 預設值為 1024:524288(軟性上限 1,024) - accept(2) — Linux manual page Linux man-pages
處理程序碰到 fd 上限時,accept 以 EMFILE 失敗 - Maximum Number of Sockets Supported Microsoft
Windows Winsock 只以可用記憶體限制 socket 數量 - pidstat(1) — Linux manual page sysstat
-v 的 fd-nr:處理程序開啟的檔案描述子數 - proc_pid_limits(5) — Linux manual page Linux man-pages
/proc/PID/limits 列出每個處理程序各項資源上限的軟性與硬性值
相關原因
同一層:L7 伺服器 OS(kernel)
同一症狀(連不上/無限讀取)在其他層的原因
查看含圖解與實驗的完整版卡片