“Too many open files”是系统级文件描述符四层限制未对齐所致,必须同步配置内核fs.file-max、用户limits.conf(含PAM启用)、systemd LimitNOFILE及nginx.conf中worker_rlimit_nofile与worker_connections关系,缺一不可。

当 Nginx 作为反向代理使用 upstream 时,若出现 Too many open files 错误,往往不是单纯因为 worker 进程的文件描述符(fd)限制太低,而是 upstream 连接数被错误配置或未合理复用,导致连接堆积、fd 耗尽。关键在于:Nginx 的 upstream 连接数 ≠ 客户端并发请求数,它受多个参数协同控制,容易被低估。
upstream 连接数的真实构成
Nginx 每个 worker 进程对一个 upstream server 建立的活跃连接数,由以下因素叠加决定:
-
keepalive N:每个 worker 进程为该 upstream 保持的空闲长连接上限(仅限 HTTP/1.1 +Connection: keep-alive) -
max_conns(需配合queue或least_conn):单个 upstream server 允许的最大并发连接数(含活跃 + 等待中),默认不限制,但不设易失控 -
未及时关闭的非 keepalive 连接:客户端请求未带
Connection: keep-alive,或后端响应头强制Connection: close,会导致每次请求新建 TCP 连接且不复用 -
worker_connections × upstream server 数量 × 负载策略放大效应:例如使用
least_conn且后端节点少,连接可能集中到某一台,加速其 fd 耗尽
快速定位是否是 upstream 连接失控
在出问题的机器上执行以下命令,重点关注实际连接数与预期是否匹配:
-
查看 Nginx 当前打开的 upstream 连接(假设 upstream 名为 backend):
ss -tnp | grep :<em>backend_port</em> | grep nginx | wc -l
(替换<em>backend_port</em>为你的后端服务端口,如 8080) -
检查 Nginx 连接统计:
启用stub_status模块后访问/nginx_status,观察Active connections和Writing数值;高Writing通常意味着连接卡在发请求或等响应 -
确认系统级 fd 使用情况:
cat /proc/$(pgrep nginx)/limits | grep "Max open files"→ 查 worker 进程软硬限制lsof -p $(pgrep nginx) | wc -l→ 实际打开 fd 总数,减去监听 socket、日志文件等,剩余即为连接相关 fd
修正 upstream 配置的关键项
在 upstream 块中加入并显式设置以下参数,避免隐式行为放大连接数:
-
必须设
keepalive N:建议设为32或64,不要过大;同时在location中配proxy_http_version 1.1;和proxy_set_header Connection '';,确保复用开启 -
限制单节点最大连接:
max_conns=32(根据后端处理能力调整),并启用queue 10 timeout=3s;,防止连接无限排队 -
关闭无意义的连接保持:
proxy_ignore_client_abort off;(默认即可),但若后端响应慢,可加proxy_next_upstream error timeout http_503;快速失败 -
避免轮询外的负载策略滥用:如非必要,不用
ip_hash或hash $request_uri,它们会抑制连接复用,导致连接分散无法回收
配套系统与内核调优不可少
即使 Nginx 配置正确,若系统层不匹配,仍会触发 Too many open files:
-
提升 Nginx worker 进程的 fd 限制:在
/etc/nginx/nginx.conf的main块中加worker_rlimit_nofile 65536; -
同步修改 systemd service 限制(如果用 systemd 启动):编辑
/etc/systemd/system/multi-user.target.wants/nginx.service,添加:[Service]LimitNOFILE=65536 -
检查内核
net.ipv4.ip_local_port_range:若短连接极多,可用sysctl net.ipv4.ip_local_port_range="1024 65535"扩大临时端口范围 -
监控连接生命周期:用
tcpdump -i any port <em>backend_port</em> -w upstream.pcap抓包,观察 FIN/RST 是否及时发出,判断是 Nginx 未关、后端未关,还是网络中间件干扰


















