Nginx报“Too many open files”本质是四层资源限制未对齐:系统fs.file-max、用户ulimit、进程worker_rlimit_nofile、容器ulimit必须逐层验证并匹配,任一层缺失都会导致accept()失败。

这个问题本质是资源瓶颈,不是配置错误或代码缺陷。关键在于确认“谁卡住了脖子”——系统、用户、进程、容器,四层限制中只要有一层没对齐,Nginx 就会反复报 accept() failed (24: Too many open files)。
查清楚当前生效的文件描述符限制在哪一层
别猜,用命令直接看真实值:
- 查系统总上限:
cat /proc/sys/fs/file-max(建议高并发场景 ≥ 1000000) - 查 Nginx 主进程实际运行用户(比如
www-data或nginx):ps -eo user,comm | grep nginx | grep master - 切换到该用户,查其真实软硬限制:
sudo -u www-data bash -c 'ulimit -Sn; ulimit -Hn' - 查正在运行的 Nginx 进程已加载的限制:
cat /proc/$(pidof nginx)/limits | grep "Max open files" - 查当前打开的文件数(粗略评估使用率):
lsof -p $(pidof nginx) | wc -l
重点验证 limits.conf 是否真正生效
很多环境改了 /etc/security/limits.conf 却没效果,是因为 systemd 启动的服务默认不读取 PAM limits。验证方式很直接:
- 如果
sudo -u www-data bash -c 'ulimit -n'输出仍是 1024,说明 limits.conf 没起作用 - 常见原因:systemd 服务绕过了 PAM,需额外配置
/etc/systemd/system/nginx.service.d/override.conf,加入LimitNOFILE=65535 - 改完记得重载:
systemctl daemon-reload && systemctl restart nginx
检查 Nginx 自身配置是否匹配系统能力
worker_rlimit_nofile 和 worker_connections 必须协同设置:
- 在
nginx.conf全局块中必须设worker_rlimit_nofile 65535;(不能只靠系统限制) -
events { worker_connections 4096; }的值 ×worker_processes(如 auto 得到 4)应 ≤worker_rlimit_nofile值 - 反向代理场景下,一个请求常消耗 3–5 个 FD(client + upstream + log + temp file),所以
worker_connections不宜盲目设到 65535
Docker 环境要单独处理容器级限制
Docker 默认 FD 上限极低(常为 1024),即使宿主机调高也没用:
- 启动容器时加参数:
--ulimit nofile=65535:65535 - 或在
docker-compose.yml中写:ulimits: { nofile: { soft: 65535, hard: 65535 } } - 容器内仍需配置
worker_rlimit_nofile,且确保镜像启动用户与 limits 设置一致
排查顺序就是从外到内:系统 → 用户 → 进程 → 容器 → Nginx 配置。每一步都用命令验证,而不是假设它“应该生效”。


















