当 Nginx 日志中反复出现 too many open files 时,先不要急着把 worker_connections 调得更大。这类错误的真正含义是某个 worker 进程已经达到生效的文件描述符上限,可能是操作系统层面的限制,也可能是 Nginx 自身没有通过 worker_rlimit_nofile 提高进程级限制。本文先讲清机制,再给出配置计算和验证方法。

一、worker_rlimit_nofile 的作用与系统限制
worker_rlimit_nofile 是 Nginx 核心模块提供的 main 级指令,用于设置每个 worker 进程可打开的最大文件描述符数量。语法非常简单:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 20480;
}
默认情况下,如果省略这条指令,Nginx worker 进程会继承启动环境的文件描述符限制,例如 shell 中的 ulimit -n 值或 systemd 服务配置中的 LimitNOFILE。很多系统默认只有 1024,这对高并发 Nginx 来说远远不够。一旦连接数、代理连接、静态文件句柄和日志句柄加在一起超过这个值,就会出现打开文件过多错误。
配置该指令后,Nginx 在启动时会通过 setrlimit(RLIMIT_NOFILE, ...) 尝试同时提高软限制和硬限制。但进程能否成功调到目标值,取决于启动用户是否具有提升硬限制的权限。root 用户通常可以把该值调得很高,普通用户则不能超过系统对当前用户设置的硬限制。因此 worker_rlimit_nofile 并不是一个孤立的配置,它必须与系统层面对 Nginx 运行用户的限制配合才有意义。
二、worker_rlimit_nofile 与 worker_connections 的取值关系
不少配置示例只把 worker_connections 当作最大连接数,却忽略了每个连接并不严格等于一个文件描述符。对于纯静态文件服务,一个客户端连接在响应过程中至少需要客户端 socket 和磁盘文件两个文件描述符;对于反向代理场景,一个客户端连接通常对应一个上游连接,因此至少占用两个 socket,再加上监听 socket、事件机制、日志文件和 DNS 查询等,实际文件描述符消耗往往会比 worker_connections 大不少。
Nginx 官方文档给出的基本建议是把 worker_rlimit_nofile 设置为 worker_connections 的两倍以上,并留出一定余量。可以用这样一个简单公式:
worker_rlimit_nofile >= worker_connections * 2 + 1024
假设 worker_connections 设置为 20480,那么 worker_rlimit_nofile 至少应该是 41984,实际配置成 51200 或 65535 会更稳妥。需要注意的是,这里的 worker_connections 是每个 worker 进程的最大连接数,而不是整个 Nginx 的总连接数。每个 worker 独立完成连接处理,因此每个 worker 都要能打开足够的文件描述符。
如果启用了 proxy_pass、fastcgi_pass、uwsgi_pass 等代理模块,每个请求在完成响应之前可能同时持有客户端连接和上游连接,并且还有连接超时重试等情况,实际峰值会更高。此时按照三倍甚至更大来设置 worker_rlimit_nofile 更为合理。
三、系统层文件描述符限制配置
Linux 系统对文件描述符的限制分布在多个层面。最常接触的是用户级软限制和硬限制,可以通过 ulimit -Sn 和 ulimit -Hn 查看:
ulimit -Sn ulimit -Hn
如果要持久化修改某个用户的限制,可以在 /etc/security/limits.conf 中添加:
nginx soft nofile 65535 nginx hard nofile 65535
不过需要特别注意,如果你的 Nginx 是通过 systemd 管理的,limits.conf 中的配置不一定生效。systemd 服务默认可能使用自己的 LimitNOFILE 设置,最可靠的方式是在 Nginx 的 service 文件中加入:
[Service] LimitNOFILE=65535
修改完成后执行 systemctl daemon-reload 并重启 Nginx。如果仍无法提升,还需要查看内核全局限制。例如 /proc/sys/fs/nr_open 限制了单个进程可以设置的最高文件描述符数。若 worker_rlimit_nofile 设置的值大于 nr_open,即使以 root 身份启动也无法超过,需要先调整内核参数 fs.nr_open 和 fs.file-max,然后通过 sysctl 使其生效。
四、配置后的验证与错误排查
配置完成后不能只看 Nginx 是否启动成功,还要确认 worker 进程实际获得的限制。可以先找到 Nginx 主进程或 worker 进程的 PID,然后执行:
cat /proc/主进程PID/limits | grep -E 'Max open files'
如果输出中的软限制和硬限制已经变成配置的 65535,说明指令和系统权限都正确。还可以用 lsof -p worker进程PID 查看当前该进程实际打开的文件描述符数量,观察压测时是否接近上限。
当 Nginx 错误日志里出现 accept 或 socket 相关错误时,优先检查以下几个点:第一,worker_rlimit_nofile 是否真的写在 main 上下文,而不是误放在 http、server 或 location 中;第二,系统 ulimit -Hn 是否小于配置值;第三,systemd 的 LimitNOFILE 是否覆盖了 limits.conf;第四,是否只调大了 worker_connections 却没有同步调整文件描述符限制。只要抓住单个 worker 进程的文件描述符消耗与系统硬限制这两条线,大部分打开文件过多问题都能快速定位。
Nginxworker_rlimit_nofile文件描述符修改时间:2026-08-24 02:55:52