首页 > Technology > 正文

Nginx 高并发报 Too many open files 怎么破

fenij 2026-08-17 37 Technology

大促或压测时 Nginx 突然开始成片 502/504,错误日志满屏 Too many open files,根因几乎都是文件描述符(FD)上限太小——Docker 默认只有 1024,并发一上来就被锁死。把上限调大到 65535,再配合重试机制,基本能稳住。

一、现象:高并发下 502/504 突增

平时好好的,一旦并发冲到两三千就开始大面积 502,Nginx 的 error.log 里反复出现:

2026/08/15 21:03:11 [alert] 12#12: *1024 open() "/var/www/..." failed (24: Too many open files)

每个 TCP 连接、每个被代理的后端 socket 都要占一个 FD。1024 的上限在大并发下几秒就被吃光,新连接直接被拒,表现就是雪崩式 502。

二、先看当前的 FD 上限

进到 Nginx 进程里确认限制有没有生效:

docker exec -it my-nginx sh -c "cat /proc/\$(pidof nginx | awk '{print \$1}')/limits | grep 'open files'"
# 期望看到:Max open files  65535  65535  files

如果还是 1024 1024,说明容器默认 ulimit 没改,后面怎么配 Nginx 都没用。

⚠️
调优前
默认 ulimit 1024
并发 2000 即崩
错误率 15%

调优后
nofile 65535
峰值 QPS 3500
错误率 0.02%

三、Docker 环境:–ulimit 调大

最直接的办法是启动时把容器 FD 上限拉高:

docker run -d --name my-nginx \
  --ulimit nofile=65535:65535 \
  -p 80:80 nginx:alpine

用 Compose 的话在 service 下加:

services:
  nginx:
    image: nginx:alpine
    ulimits:
      nofile:
        soft: 65535
        hard: 65535

四、裸机 / Nginx 配置:rlimit 与连接数

容器外,还要在 nginx.confevents 块里同步调高 worker 自身的上限:

worker_rlimit_nofile 65535;
events {
    worker_connections 10240;
}

注意 worker_connections 不能超过系统 ulimit,否则 Nginx 起不来。云服务器裸机还要看 /etc/security/limits.conf 里 nginx 用户的 nofile 限制。

五、开启 proxy_next_upstream 自动重试

即使后端偶发故障,也让 Nginx 自动换一个上游重试,用户基本无感:

proxy_next_upstream error timeout http_502 http_504;
proxy_connect_timeout 10s;
proxy_read_timeout 60s;

六、上线前用压测验证是否真稳了

改完配置别凭感觉,直接压一遍看 FD 还够不够。用 wrk 打 3000 并发持续一分钟:

wrk -t4 -c3000 -d60s http://你的域名/

压测同时另开一个窗口盯 Nginx 的 FD 占用,确认峰值下离上限还有余量:

watch -n1 "ls /proc/\$(cat /run/nginx.pid)/fd | wc -l"

如果压到目标并发 FD 占用稳定在几万、错误率接近 0,说明调优到位;要是 FD 数字顶到上限就掉错误,说明 --ulimitworker_rlimit_nofile 还没真生效,回去重查容器重建和配置 reload 有没有漏。

生产环境建议把 Nginx 的 stub_status 打开,长期盯活跃连接数和请求速率,能在 FD 快被吃满之前提前告警,而不是等雪崩了才反应。配置里加一段 location /nginx_status { stub_status on; allow 127.0.0.1; deny all; },再用 curl 127.0.0.1/nginx_status 就能看到实时连接分布。

踩坑实录

一次大促前压测,并发到 2000 就大面积 502,Nginx 日志满屏 “Too many open files”。我第一反应是加 proxy_next_upstream error timeout http_502;,以为重试能扛住。结果重启后撑不过两分钟又崩。进容器 cat /proc/self/limits | grep "open files" 一看,Max open files 还是 1024。原来容器默认 ulimit 根本没动,retry 只是把请求推给已经没有 FD 的后端,纯属治标。加上 --ulimit nofile=65535:65535 后,峰值 QPS 从 800 拉到 3500,错误率从 15% 降到 0.02%。教训:FD 上限是地基,重试只是上层建筑,地基不牢先补地基。

常见问题

Q:改了 ulimit 还是报 Too many open files?
A:八成是 Nginx 的 worker_rlimit_nofile 没跟着改,或 Compose 改了 run 参数却没 docker compose up -d 重建容器。两个值要一起调,且容器内验证过才算数。

Q:worker_connections 设多大合适?
A:一般设 worker_processes × worker_connections 略大于预期并发。单 worker 10240、开 4 个 worker 就是四万多连接上限,足以覆盖绝大多数中小站点。

Q:只调 Nginx 不调系统够吗?
A:Docker 场景下只调 Nginx 配置没用,容器的 ulimit 是父级限制,必须先 --ulimit 放开,Nginx 才能用得上。

高并发下的 Nginx 调优是个系统工程,FD 上限只是第一道关。如果你在压测或上线时还遇到别的瓶颈,欢迎到 fenij.com 留言,一起把这套调优清单补齐。

相关完整手册

系统化的排查与配置思路,建议顺手收藏这几篇完整手册: