真实高并发压测是验证fd是否够用的最硬标准,需用wrk/hey强制新建连接、观察accept失败/502/连接重置等信号,并同步检查lsof统计、file-nr、worker_rlimit_nofile及TIME_WAIT堆积情况。

直接在真实高并发场景下验证文件描述符(fd)是否够用,是判断调优是否落地的最硬标准。关键不是看配置写了多少,而是压测时系统有没有因 fd 耗尽而报错、连接是否被静默丢弃、QPS 是否在某个并发点突然塌方。
用 wrk/hey 模拟极限连接并观察失败信号
避免用 ab 做高并发测试——它自身容易成为瓶颈。推荐使用 wrk 或 hey,并强制新建连接:
- 加 --disable-keepalive 参数,确保每个请求都消耗一个新 fd(例如:
wrk -t4 -c5000 -d60s --disable-keepalive http://127.0.0.1/) - 并发数要明显超过理论最大连接数:比如你设了
worker_processes 4、worker_connections 10240,那理论上限是 40960;压测就从-c 45000起步 - 重点盯三类失败反馈:
– Nginx 错误日志中出现 accept() failed (24: Too many open files)
– 响应里大量返回 502 Bad Gateway 或直接超时(非后端问题时,大概率是 worker 进程拿不到 fd)
– 客户端统计的 Failed requests 突然跳升,且错误类型集中为 connection reset / refused
同步检查系统级 fd 使用与限制
光看 Nginx 日志不够,得确认操作系统是否真卡在了 fd 上:
- 实时查当前 Nginx 进程打开的 fd 数:
lsof -p $(pgrep nginx) | wc -l,对比ulimit -n输出值 - 查整个系统的已分配 fd 总量:
cat /proc/sys/fs/file-nr(三列数字,重点关注第二列“已分配但未释放”) - 确认
worker_rlimit_nofile已生效:nginx -T | grep worker_rlimit_nofile,且该值必须 ≥worker_processes × worker_connections - 若发现
lsof统计接近ulimit -n,但压测还没到预期并发,说明limits.conf未对 Nginx 启动上下文生效(常见于 systemd 启动,需额外配LimitNOFILE=)
结合连接状态与 TIME_WAIT 行为交叉验证
fd 不足常和大量 TIME_WAIT 共存,二者会互相加剧:
- 用
ss -s查看 TCP 连接总数及 TIME_WAIT 数量:ss -s | grep -E "(TCP|time)" - 若 ESTABLISHED 连接远低于预期,但 TIME_WAIT 占满 80% 以上,说明连接释放慢,挤压了可用 fd;此时需配合调优
net.ipv4.tcp_tw_reuse = 1和keepalive_timeout - 观察
ss -tan state time-wait | wc -l是否随压测时间线性增长却不回落——这是连接未及时回收的信号,可能源于 upstream keepalive 未开或后端响应慢导致连接挂起
做阶梯式饱和压测并记录拐点
不要只跑一次极限值,要找“崩溃临界点”:
- 固定其他参数,逐步提升并发:从
-c 1000 → 5000 → 10000 → 20000,每档压测 2 分钟 - 记录每档的 QPS、P99 延迟、失败率、Nginx error.log 中 fd 相关错误条数
- 拐点特征:QPS 停滞甚至下降、P99 延迟陡增 3 倍以上、失败率从 0% 突增至 >5%,同时
lsof接近 ulimit 上限 → 此即当前 fd 配置的实际承载天花板 - 若拐点明显低于理论值(如理论 40960,实测 25000 就崩),说明还有隐藏限制没放开(如 systemd 的 LimitNOFILE、容器 cgroup 限制、SELinux 策略拦截)











