先把当时的情况摆出来。用 ab -n 100000 -c 500 压一台四核八 G 的 CentOS 7.9 上的 nginx,跑到一半大量报 Connection reset by peer,失败请求占三成,error.log 里是 worker_connections are not enough。

真正麻烦的地方在于,几个原因的现象几乎一样。worker_connections 是默认的 512,代理场景下客户端和上游各占一个。还有一种是listen 的 backlog 太小,握手阶段就开始丢。

不容易想到的是,压测机 ulimit -n 只有一千零二十四,端口用完就重置。还有一种情况,链路中间过了一层 NAT,空闲连接被提前回收。

先看 nginx 错误日志确认丢弃类型

tail -200 /var/log/nginx/error.log | grep -iE 'limit|enough'

调大每进程连接数与句柄

sed -i 's/worker_connections 512/worker_connections 65535/' /etc/nginx/nginx.conf

接着核对内核队列与句柄余量

sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog && ulimit -n

reload 之后按同样并发重压

nginx -t && nginx -s reload

怎么算真的好了,看的是同一批现象。五百并发下失败率降到千分之一以内,error.log 不再出现连接数不足的提示,ab 汇总里的非二开头响应归零。

这里还有个坑。worker_connections 是单进程能同时处理的连接总数,反代场景要按并发乘二再留三成余量,光改数字不改句柄仍然会卡。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189