“accept() failed (24: too many open files)”表明nginx worker进程无法获取新文件描述符,真正瓶颈需分层定位:若仅个别worker(如pid 1234)高频报错,应检查其对应upstream配置、后端服务fd限制及连接回收是否异常;若所有worker同步报错且dmesg提示file-max告警,则为系统级fd耗尽。

看到 Nginx 错误日志里反复出现 accept() failed (24: Too many open files),说明文件描述符(fd)耗尽了。但这个报错只反映“Nginx worker 拿不到新 fd”,真正瓶颈可能在 Nginx 自身,也可能在后端服务(如 PHP-FPM、Node.js、上游代理等)。关键不是猜,而是分层定位。
看错误是否集中在特定 worker 进程
- 如果只有个别 worker(比如 PID 1234、5678)持续报错,其他 worker 正常 → 大概率是该 worker 对应的连接池、长连接或 upstream 超时未释放,问题更可能出在 Nginx 配置或其直连的后端服务上
- 可用命令快速确认:
grep "accept() failed" /var/log/nginx/error.log | awk '{print $NF}' | cut -d',' -f1 | sort | uniq -c | sort -nr若输出中某几个 PID 明显高频,就先盯住它们
查看后端服务是否也在耗尽 fd
- 登录对应后端服务所在机器(或容器),执行:
# 查看该服务主进程实际打开的 fd 数量 lsof -p $(pgrep -f "php-fpm\|gunicorn\|node") | wc -l # 或直接看 limits cat /proc/$(pgrep -f "php-fpm")/limits | grep "Max open files"
- 如果后端服务的
Max open files也是 1024,且lsof数量接近该值 → 它自身 fd 不足,会拖累 Nginx(例如 upstream keepalive 连接卡住、超时未断开)
检查 Nginx 是否把 fd “借”给了后端却没回收
- 启用
upstream的keepalive时,Nginx 会为每个 upstream server 维护连接池;若后端响应慢、超时设置不合理(如proxy_read_timeout过长),连接会长期占用 fd - 常见配置风险点:
-
proxy_http_version 1.1;+proxy_set_header Connection '';但没配keepalive 32; -
keepalive_requests 1000;过高,而keepalive_timeout 60s;又太长,导致连接堆积
-
- 建议加监控:
http { log_format fd_debug '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'upstream_addr:$upstream_addr upstream_status:$upstream_status'; }结合
upstream_status和upstream_addr,能快速识别是哪个后端节点拖慢了连接释放
用 lsof 对比 Nginx 与后端的 fd 类型分布
- 分别对 Nginx master、worker、后端主进程执行:
lsof -p <pid> | awk '{print $9}' | cut -d':' -f1 | sort | uniq -c | sort -nr</pid> - 若 Nginx worker 中大量是
socket、anon_inode(epoll)、pipe,而REG(普通文件)很少 → 是网络连接占满,问题大概率在并发模型或 upstream - 若后端进程中大量是
socket+REG(比如日志文件、缓存文件未关闭),说明它存在 fd 泄漏,Nginx 只是“被连累”
不复杂但容易忽略











