“too many open files”是系统文件描述符四层限制(内核fs.file-max、用户limits.conf、systemd limitnofile、nginx worker_rlimit_nofile与worker_connections)未对齐所致,须全部同步调优并逐层验证生效,缺一不可。

“Too many open files”不是 Nginx 配置写错了,而是系统对文件描述符(FD)的四层限制没对齐——内核、用户、进程启动环境、Nginx 自身配置,缺一不可。只改其中一层,比如只调 nginx.conf 或只运行 ulimit -n 65535,基本无效。排查必须逐层验证实际生效值,而不是猜或跳步。
查清哪一层真正卡住了
别依赖印象或配置文件是否修改过,直接读进程和内核的真实状态:
- 系统全局上限:
cat /proc/sys/fs/file-max(建议 ≥ 200000,高并发推荐 1048576) - Nginx 用户软/硬限制:
sudo -u nginx bash -c "ulimit -Sn && ulimit -Hn" - Nginx master 进程实际限制:
cat /proc/$(cat /var/run/nginx.pid)/limits | grep "Max open files" - Nginx worker 进程限制:
ps --ppid $(cat /var/run/nginx.pid) -o %p | sed '1d' | xargs -I{} cat /proc/{}/limits | grep "Max open files"
重点关注每行输出中第一个数字(软限制),它才是当前生效的天花板。如果 worker 进程显示 1024 4096,而其他层都已是 65535,说明问题出在 Nginx 配置或启动环境;如果所有层都是 1024,那大概率是 limits.conf 没生效或 PAM 未启用。
检查 limits.conf 是否真正起效
这是最常踩的坑。改完 /etc/security/limits.conf 后仍不生效,通常因为以下三点:
- 没指定 nginx 用户:应明确添加两行,而非仅用
*:nginx soft nofile 65535nginx hard nofile 65535 - PAM 模块未启用:确认
/etc/pam.d/common-session(Ubuntu/Debian)或/etc/pam.d/login(CentOS/RHEL)中含session required pam_limits.so - 未使用新会话验证:改完后需用
su - nginx -c 'ulimit -n'测试,或重启 systemd 服务(若用 systemd 启动)
验证 Nginx 自身配置是否联动成功
即使系统和用户层都调高了,Nginx 仍需主动申请并合理分配 FD 资源:
- 全局块(main context)必须有:
worker_rlimit_nofile 65535; - events 块中
worker_connections必须 ≤worker_rlimit_nofile(例如设为 4096 或 8192) - 重启 Nginx 后,再次检查 worker 进程的
/proc/*/limits,应显示类似:Max open files 65535 65535 files - 同时确认 error.log 不再出现
accept() failed (24: Too many open files)或socket() failed (24: Too many open files)
Docker 环境要额外检查容器级限制
若 Nginx 运行在 Docker 中,容器默认 FD 上限常为 1024,必须显式放开:
- docker run 启动时加参数:
--ulimit nofile=65535:65535 - docker-compose.yml 中配置:
ulimits: nofile: {soft: 65535, hard: 65535} - Kubernetes 中需在容器启动命令里嵌入:
ulimit -n 65535 && nginx -g 'daemon off;' - 容器内还要同步配置
nginx.conf的worker_rlimit_nofile和worker_connections











