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

游戏卡顿白皮书 › L7 服务器操作系统(内核)

文件描述符上限 File descriptor limit (ulimit)

原因 ID so-fd · 主责 运维团队·系统运维 · 配合 研发团队·服务器开发

在含图示和实验的完整版中打开此卡片 →

每个连接都要占用一个文件描述符(fd,操作系统给打开的文件、socket 分配的编号),而一个进程能打开的 fd 数量是有限的。

起因 同时在线人数达到进程的文件描述符上限 → 结果 服务器无法接受新连接(Too many open files),打开日志、建立 DB 连接也一起失败 → 画面表现 从某个固定人数开始谁都进不来,表现为连不上/无限加载

症状
连不上/无限加载
因素
丢包
谁会遇到
全服
何时出现
刚登录/维护结束后, 人多的时候
负责方
主责 运维团队·系统运维 · 配合 研发团队·服务器开发
研发团队要做的事
结束连接时务必关闭 socket(防止 fd 泄漏);accept 因 EMFILE(fd 不足)失败时,先暂停接受连接一会儿,或用预先留出的备用 fd 接下连接后立即关闭(以免反复处理同一个连接通知、白白消耗 CPU)。
运维团队要做的事
检查 ulimit 和服务配置(systemd 的 LimitNOFILE);接近上限时告警。
数值参考
Linux 在不单独配置服务的情况下,上限仍常常是 1,024。游戏服务器通常会调到数万到数十万。Windows 没有这么低的默认上限。
监控图上
触顶后走平 · 进程打开的 fd 数、同时在线人数
查看位置
用 pidstat -v 看游戏服务器进程的 fd-nr(打开的文件描述符数),用 /proc/PID/limits 看打开文件数上限,在服务器日志里找 accept 失败(EMFILE、Too many open files)
确认依据
fd 数在上限值处走平,从那一刻起 accept 以 EMFILE 失败
排除依据
fd 数离上限还很远则不是这个原因。连接请求在内核被丢弃,看“连接队列(backlog)溢出”;问题在连接跟踪,看“服务器 conntrack 表耗尽”
确认手段
运维工具即可确认(无需游戏代码)
深入了解
没被接受的连接仍留在内核连接队列(backlog)里。视服务器代码而定,进程可能会不断收到“有新连接”的通知,白白浪费 CPU。

出处

  1. systemd-system.conf(5) — Linux manual page systemd
    服务的 DefaultLimitNOFILE 默认值为 1024:524288(软上限 1,024)
  2. accept(2) — Linux manual page Linux man-pages
    达到进程的 fd 上限时,accept 以 EMFILE 失败
  3. Maximum Number of Sockets Supported Microsoft
    Windows Winsock 只按可用内存限制 socket 数量
  4. pidstat(1) — Linux manual page sysstat
    -v 的 fd-nr:进程打开的文件描述符数
  5. proc_pid_limits(5) — Linux manual page Linux man-pages
    /proc/PID/limits 里有进程各项资源上限的软、硬值

相关原因

同一层:L7 服务器操作系统(内核)

其他层中同样导致“连不上/无限加载”的原因

查看含图示和实验的原卡片