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

处理千万级小文件时,Nginx 最常卡在“Too many open files”——这不是配置没加,而是整条句柄限制链路没打通。关键不在 worker_connections 多高,而在每个 worker 进程能合法打开多少文件描述符(fd),这由系统限制、PAM 加载、systemd 约束、Nginx 自身指令四层共同决定。
确认当前真实限制值
别信配置文件,要看进程实际生效值:
- 查 Nginx worker 进程当前限制:
cat /proc/$(pgrep -f "nginx: worker" | head -n1)/limits | grep "Max open files"
输出中 Soft Limit 必须等于你预期的值(如 131072),否则后续全白调 - 查系统全局上限:
cat /proc/sys/fs/file-max
建议设为句柄总需求的 2 倍以上(例如 16 个 worker × 131072 ≈ 209 万,则 fs.file-max ≥ 4194304) - 查当前用户会话限制:
ulimit -n
仅反映 shell 启动环境,不能代表 Nginx 实际继承值
四层限制必须全部对齐
缺一不可,漏一层就静默失效:
-
/etc/security/limits.conf:指定运行用户(如 www-data 或 nginx)的 soft/hard nofile
示例:www-data soft nofile 131072www-data hard nofile 131072 -
PAM 模块启用:确保 /etc/pam.d/common-session 包含
session required pam_limits.so -
systemd 服务覆盖(若用 systemctl 启动):
创建/etc/systemd/system/nginx.service.d/override.conf,内容为:[Service]LimitNOFILE=131072 -
Nginx 主配置(main 上下文):必须写在 events 和 http 块之外、最外层
worker_rlimit_nofile 131072;
该值 ≤ hard nofile,建议取硬限制的 90%
关联参数要合理配比
光堆大数字没用,还要留余量防挤占:
-
worker_connections应 ≤worker_rlimit_nofile × 0.7
例如设 131072,则 worker_connections 推荐 ≤ 90000,为日志、SSL 缓存、upstream socket 预留空间 - 启用
open_file_cache减少重复 open/close 开销:open_file_cache max=65536 inactive=60s;open_file_cache_valid 60s;open_file_cache_min_uses 2; - 避免日志频繁刷盘占用 fd:
用access_log /path/log main buffer=64k flush=5s;
验证与日常监控建议
改完不验证=没改:
- 重启生效:
systemctl restart nginx
注意:reload 不重置 fd 限制,必须 restart - 实时观察 fd 使用量:
watch -n 1 'lsof -p $(pgrep -f "nginx: worker" | head -n1) | wc -l' - 错误日志重点搜:
grep -i "too many open files\|EMFILE\|accept() failed" /var/log/nginx/error.log - 发现异常上涨时,用
lsof -p PID -n | awk '{print $9}' | sort | uniq -c | sort -nr | head -20查看哪些路径占 fd 最多











