“too many open files”是系统文件描述符四层限制未对齐所致,须同步调整内核fs.file-max、用户limits.conf、systemd limitnofile及nginx.conf中worker_rlimit_nofile与worker_connections,缺一不可。

遇到 Nginx 返回 502 或连接被拒(Connection refused / Connection reset),但后端服务本身运行正常,很可能是文件句柄(file descriptor)耗尽导致的——这不是 Nginx 配置写错了,而是系统资源卡在了“打开多少个文件”这道门槛上。
看日志确认是不是句柄问题
先别改配置,直接查 Nginx 错误日志:
- 执行 tail -f /var/log/nginx/error.log
- 搜索关键词:“too many open files”、“open file resource limit”、“accept() failed”
- 如果出现类似 “worker_connections are more than open file resource limit”,基本就是它了
查当前生效的文件句柄限制
注意:Nginx 工作进程继承的是其启动用户的限制,不是你当前终端的 ulimit 值。
- 用 ps aux | grep nginx 看主进程运行用户(比如 www-data、nginx 或 root)
- 切换到该用户(如 sudo -u www-data bash),再运行 ulimit -n
- 若输出是 1024 或 4096,说明太低;理想值应 ≥65535
同步调三处限制,缺一不可
只改 Nginx 配置没用,必须让“内核 → 用户 → 进程”三级一致:
- /etc/sysctl.conf 加:fs.file-max = 65535,然后 sysctl -p
-
/etc/security/limits.conf 加两行(把 www-data 换成实际用户):
www-data soft nofile 65535
www-data hard nofile 65535 - nginx.conf 在 events 块外、http 块前加:worker_rlimit_nofile 65535;
配套检查后端服务是否跟上
Nginx 打开了 6.5 万个句柄,但 PHP-FPM 或 Tomcat 还卡在默认 1024,照样会崩:
- PHP-FPM:确认 php-fpm.conf 中有 rlimit_files = 65535,且 pm.max_children 设置合理(内存够才敢设高)
- Tomcat:检查 server.xml 的 maxConnections 和系统级 net.core.somaxconn
- 重启顺序:先 reload sysctl & limits,再重启 PHP-FPM/Tomcat,最后 nginx -s reload











