遇到“accept() failed (24: Too many open files)”可锁定为文件描述符耗尽,需逐层排查系统全局(fs.file-max)、用户级(limits.conf)、systemd级(LimitNOFILE)、Nginx级(worker_rlimit_nofile与worker_connections)四层限制是否对齐,并同步检查upstream连接泄漏、日志/SSL/缓存等冗余fd占用。

遇到连接崩溃,尤其是报 accept() failed (24: Too many open files) 或 socket() failed (24: Too many open files),基本可以锁定是文件句柄(file descriptor, FD)耗尽。这不是 Nginx 配置写错了,而是系统资源被撑满——就像服务员身上挂满了房卡,再有客人来,只能拒之门外。
看真实限制在哪一层卡住
文件句柄限制分四层,漏调一层就白忙:系统全局、用户级、进程级、Nginx 自身配置。必须逐层确认是否对齐:
- 查系统总上限:
cat /proc/sys/fs/file-max→ 建议设为 ≥100 万(高并发场景) - 查当前 nginx worker 进程实际生效值:
cat /proc/$(pgrep nginx | head -1)/limits | grep "Max open files"→ 关注 soft 和 hard 两列数字 - 查 nginx 进程打开的 fd 总数:
lsof -p $(pgrep nginx) | wc -l→ 减去固定开销(如 0/1/2 标准流、日志文件、配置文件等),剩余即为连接相关 fd - 查是否真在耗尽:
ss -s看 total established + time-wait 是否接近你预设的worker_connections × worker_processes
快速验证是不是 upstream 连接失控
反向代理场景下,upstream 连接数常被严重低估。一个客户端请求可能触发多个上游连接(尤其未复用时),导致 fd 暴涨:
- 统计到后端端口的实际连接:
ss -tnp | grep :8080 | grep nginx | wc -l(把 8080 换成你的 upstream 端口) - 检查
/nginx_status(需启用 stub_status)→ 若 Writing 值持续偏高,说明连接卡在发请求或等响应,大概率是 upstream 建连失败或响应慢引发堆积 - 确认 upstream 是否启用了 keepalive:没配
keepalive 32;,又没在 location 中加proxy_http_version 1.1;和proxy_set_header Connection '';,那每次请求都新建 TCP 连接
同步调优四层限制,一个都不能少
只改 worker_connections 是无效的。必须让四层限制“对齐”,且 Nginx 能真正拿到足够 fd:
- 系统级:
echo 'fs.file-max = 1048576' >> /etc/sysctl.conf && sysctl -p - 用户级(以 nginx 用户为例):
echo -e "nginx soft nofile 65536\nnginx hard nofile 65536" >> /etc/security/limits.conf - systemd 级(若用 systemd 启动):在
/etc/systemd/system/nginx.service的 [Service] 下加LimitNOFILE=65536,然后systemctl daemon-reload - Nginx 配置级:在
nginx.conf的 main 上下文中加worker_rlimit_nofile 65536;;events 块中worker_connections建议设为 50000~60000(留出 10%~20% 给日志、SSL 缓存、临时文件等)
减少不必要的 fd 占用
即使上限调高,泄漏或冗余也会加速耗尽:
- 关闭不必要日志:
access_log off;或启用缓冲:access_log /var/log/nginx/access.log buffer=64k flush=5s; - 检查是否加载了冗余模块(如未用的第三方模块),它们可能悄悄占用 fd
- 确认 SSL 配置:OCSP stapling、session cache 若未合理设置,会在高并发下生成大量临时 fd
- 避免在 location 中频繁
open_file_cache大量小文件,缓存条目本身也占 fd


















