“too many open files”是系统、用户、进程、nginx四层文件描述符限制未对齐所致,必须逐层验证并同步配置:内核fs.file-max、用户limits.conf(含pam启用)、systemd limitnofile及nginx.conf中worker_rlimit_nofile与worker_connections关系,缺一不可。

“Too many open files”不是 Nginx 配置写错了,而是文件描述符(FD)在系统、用户、进程、Nginx 四层限制中某一层卡在默认值(通常是 1024),导致连接无法建立。排查必须逐层验证,不能只调一个地方。
先查清哪一层真正卡住了
别猜,直接看进程实际生效值:
- 系统全局上限:cat /proc/sys/fs/file-max(建议 ≥ 200000)
- Nginx 用户软硬限制:sudo -u nginx bash -c 'ulimit -Sn && ulimit -Hn'(若仍是 1024,说明 limits.conf 或 PAM 没生效)
- 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 是最常见失效点)
重点检查 limits.conf 为什么没生效
改完 limits.conf 却不生效,大概率是以下三处漏了:
- 没写明 nginx 用户:光写 * soft nofile 65535 不够稳妥,必须加 nginx soft nofile 65535 和 nginx hard nofile 65535
- PAM 模块未启用:Debian/Ubuntu 查 /etc/pam.d/common-session,CentOS/RHEL 查 /etc/pam.d/login,确认含 session required pam_limits.so
- systemd 启动覆盖了 limits:执行 sudo systemctl edit nginx,填入 [Service] LimitNOFILE=65535,再重载重启
确认 upstream 连接是否失控
反向代理场景下,upstream 连接数容易被低估,造成 FD 快速耗尽:
- 用 ss -tnp | grep :8080 | grep nginx | wc -l(替换为你的后端端口)查看真实 upstream 连接数
- 启用 stub_status 后访问 /nginx_status,重点关注 Writing 值——持续偏高说明请求卡在发往后端或等响应
- 检查 upstream 块是否配置了 keepalive 32,且对应 location 中有 proxy_http_version 1.1 和 proxy_set_header Connection ''
- 避免不设 max_conns,建议显式写 max_conns=32 防止单节点连接爆炸
验证 Nginx 自身配置联动是否合理
worker_rlimit_nofile 不是并发数,它是每个 worker 进程能打开的**所有文件描述符总数**(含日志、配置、socket 等):
- 确保 worker_rlimit_nofile ≥ worker_connections × worker_processes
- events 块中设 worker_connections 4096(不要盲目设到 65535)
- 全局块中设 worker_rlimit_nofile 65535,并确认该值已在 worker 进程的 /proc/*/limits 中体现
- 错误日志要能捕获 alert 级别:error_log /var/log/nginx/error.log alert;,否则看不到 “failed (24: Too many open files)”











