根本原因是系统文件描述符(fd)上限不足,须系统级、进程级、Nginx配置三级联动:先查真实限制(用户ulimit、systemd LimitNOFILE、worker进程/proc/pid/limits),再分别调整/etc/security/limits.conf或systemd override.conf、nginx.conf中worker_rlimit_nofile(main上下文,≤硬限制),并设worker_connections为该值的70%~90%,最后restart而非reload。

直接说重点:Nginx 报 Too many open files 或启动失败提示 setrlimit(RLIMIT_NOFILE) failed,根本原因不是 Nginx 配置错了,而是系统没给够“开门的钥匙”——文件描述符(fd)上限太低。只改 worker_rlimit_nofile 是无效的,必须系统级、进程级、Nginx 配置三级联动。
确认当前限制在哪卡住了
别猜,先查真实值:
- 看 Nginx 主进程用的什么用户:
ps -eo pid,comm,user | grep nginx | grep master(常见为www-data或nginx) - 查该用户的软硬限制:
sudo -u nginx bash -c "ulimit -Sn; ulimit -Hn" - 查 systemd 服务限制(若用 systemd):
systemctl show nginx | grep LimitNOFILE - 查运行中 worker 进程实际生效值:
cat /proc/$(pgrep nginx | head -2 | tail -1)/limits | grep "Max open files"
同步调整系统级 nofile 限制
根据你的部署方式选一种,不能只改一处:
- 如果用 systemd(绝大多数现代发行版):
创建/etc/systemd/system/nginx.service.d/override.conf,写入:[Service]<br>LimitNOFILE=65536
然后执行:sudo systemctl daemon-reload && sudo systemctl restart nginx - 如果用传统 init 或手动启停:
编辑/etc/security/limits.conf,添加两行(用户名需匹配):nginx soft nofile 65536<br>nginx hard nofile 65536
确保/etc/pam.d/common-session包含session required pam_limits.so
配置 Nginx 的 worker_rlimit_nofile
这个值必须写在 nginx.conf 的最外层(main 上下文),不能放在 http 或 server 块里:
- 打开
nginx.conf,在events块之前、http块之外的位置添加:worker_rlimit_nofile 65536; - 该数值必须 ≤ 系统为 Nginx 用户设置的硬限制(hard nofile),建议设为硬限制的 90% 左右,留出空间给日志、临时文件等
- 改完必须
systemctl restart nginx(不是 reload),因为限制在 worker 进程启动时就固定了
配合检查 worker_connections 和实际负载
光开大门还不够,得算清楚能进多少人:
- 总连接能力 ≈
worker_processes × worker_connections -
worker_connections建议设为worker_rlimit_nofile的 70%~90%,例如设了 65536,那worker_connections可设 50000~60000 - 每个 TCP 连接至少占 2 个 fd(客户端 socket + 日志句柄等),HTTPS 还要额外算 SSL session cache、OCSP stapling 等开销
- 用
lsof -p $(pgrep nginx | head -2 | tail -1) | wc -l查当前 worker 实际用了多少 fd,判断是否存在泄漏或冗余占用


















