根本原因是HTTPS连接实际占用3~5个文件描述符,需系统层、进程层、Nginx配置层三级联动调优:调高file-max、ulimit及systemd LimitNOFILE,配置worker_rlimit_nofile和合理worker_connections。

处理大规模并发 HTTPS 连接时,Nginx 报 too many open files 错误,根本原因不是配置写得少,而是文件描述符(FD)资源被悄悄吃光了。HTTPS 比 HTTP 多出 SSL 握手、会话缓存、OCSP stapling、证书链读取等环节,每个连接实际占用的 FD 常达 3~5 个,远超普通 TCP 连接。必须从系统层、进程层、Nginx 配置层三级联动调优,单改一处基本无效。
确认当前限制并定位瓶颈
先看真实限制,别信默认值:
- 查系统全局上限:
cat /proc/sys/fs/file-max—— 建议 ≥ 655360 - 查当前 shell 的 ulimit:
ulimit -n—— 默认常为 1024,必须提升 - 查已运行 Nginx worker 进程的实际限制:
cat /proc/$(pgrep nginx | head -1)/limits | grep "Max open files"—— 这才是 Nginx 真正在用的值
若第三条显示 soft/hard limit 仍是 1024,说明系统级或启动环境未生效,后续所有 Nginx 配置都会被截断。
系统级 ulimit 全面调高
不能只改用户 limits.conf,还要覆盖 systemd 启动场景:
- 编辑
/etc/security/limits.conf,添加(注意:nginx 用户名要和 Nginx 配置中user指令一致):nginx soft nofile 65536nginx hard nofile 65536 - 若用 systemd(绝大多数现代发行版),还需编辑
/usr/lib/systemd/system/nginx.service或/etc/systemd/system/nginx.service.d/override.conf,加入:[Service]LimitNOFILE=65536 - 临时验证可执行:
sudo -u nginx bash -c 'ulimit -n',应输出 65536
Nginx 主动接管并约束 FD 资源
仅靠系统设置还不够,Nginx 必须在 fork worker 前主动调用 setrlimit():
- 在
nginx.conf的全局块(main context)添加:worker_rlimit_nofile 65536; - 该值必须 ≤ 系统为 nginx 用户设置的 hard limit,否则 Nginx 启动失败
- 它不改变系统限制,但确保每个 worker 进程一启动就拥有明确、可控的 FD 上限,避免因启动 shell 环境差异导致行为漂移
worker_connections 与 HTTPS 实际开销匹配
HTTPS 场景下,盲目设高 worker_connections 反而容易触发 FD 耗尽:
- 每个活跃 HTTPS 连接至少消耗:1 个客户端 socket + 1 个日志句柄 + 1 个 SSL session cache slot + (可能)OCSP stapling 文件句柄
- 建议
worker_connections设为系统单进程 FD 限制的 70%~80%,例如:events {<br> worker_connections 50000;<br>} - 同时配好
worker_processes auto;,让 Nginx 自动适配 CPU 核心数;若机器 IO 密集(如大量静态文件 TLS 加密传输),可设为2 * CPU核心数 - 务必关闭不必要的模块:如不用 access_log,可关掉;不用 upstream,避免额外连接池 FD 占用


















