答案是:/proc/sys/fs/file-max和ulimit -n共同决定实际并发连接上限,前者为系统级总文件描述符上限,后者为当前shell软限制;需分别用cat /proc/sys/fs/file-max和ulimit -n查看,且真实值以/proc为准、生效需重启登录或重载systemd配置。

直接看 /proc/sys/fs/file-max 和 ulimit -n,这两个才是决定“当前能建多少连接”的实际门槛,不是配置项名,也不是理论值。
怎么查系统级总连接池上限(fs.file-max)
Linux 中每个 TCP 连接、socket、打开的文件都消耗一个文件描述符(fd),所以系统最大并发连接数直接受 fs.file-max 约束。
- 运行
cat /proc/sys/fs/file-max查当前内核允许的最大文件描述符总数 - 这个值默认约等于内存页数 × 0.1;4GB 内存机器常见为 786432 左右;若业务需支撑 50 万连接,建议设为
2097152 - 别只信
sysctl fs.file-max输出:某些发行版(如 RHEL 8+)用 systemd-sysctl 管理,sysctl显示的是缓存值,真实值以/proc/sys/fs/file-max为准 - 注意它和
pid_max无关;但若file-max超过内存能支撑的句柄数,内核会静默降级——不是报错,而是后续accept()或socket()开始随机失败
怎么查当前进程/用户能用多少连接(ulimit -n)
即使 file-max 很大,单个进程仍受 ulimit -n 限制。Java、Nginx、Node.js 启动后继承 shell 的该值,超了就报 Too many open files。
- 运行
ulimit -n查当前 shell 的软限制(soft nofile) - 运行
ulimit -Hn查硬限制(hard nofile),软限制不能超过它 - 容器内进程默认继承宿主机
ulimit,Docker 要显式加--ulimit nofile=65536:65536才生效 - systemd 服务不读
/etc/security/limits.conf,必须在 service 文件里写LimitNOFILE=65536,或全局设DefaultLimitNOFILE=65536在/etc/systemd/system.conf
为什么改了 limits.conf 还是没效果
常见失效原因有三个:
- 没配
/etc/pam.d/common-session或/etc/pam.d/sshd(Ubuntu/Debian 默认有;CentOS 需检查/etc/pam.d/system-auth) - 服务是 systemd 启动的,但没在 service 文件里加
LimitNOFILE=,或没改/etc/systemd/system.conf中的DefaultLimitNOFILE - 用户登录后未新开 shell,
ulimit -n不会自动刷新;需重新登录(SSH 断开重连,不是新开终端窗口) - 验证是否生效:先
su - $USER,再运行ulimit -n——这才是服务实际拿到的值
怎么确认是不是真瓶颈了
只查数字不够,得看实时使用水位:
- 运行
cat /proc/sys/fs/file-nr,输出三元组:已分配 fd 数未使用 fd 数最大 fd 数;第二项长期接近第一项就说明快满了 - 运行
ss -s看当前 socket 统计,重点关注sockets in use和memory usage - 对关键进程(如 nginx)验证:先
pgrep nginx拿 PID,再cat /proc/<pid>/limits | grep "Max open files"</pid>,确认 Soft/Hard Limit 是否已更新 - 注意:
ulimit -n值如果低于其他项,它就是实际瓶颈;很多服务启动时不会重新读取 limits,重启服务才生效
真正卡住连接的,往往不是哪个参数没调,而是多个维度里最小的那个值,且容易被忽略的是:systemd 服务不走 PAM、容器默认继承宿主机限制、以及 /proc/sys/fs/file-nr 第二项持续偏低——这些地方不动,光改 sysctl.conf 没用。


















