先把当时的情况摆出来。用 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 是单进程能同时处理的连接总数,反代场景要按并发乘二再留三成余量,光改数字不改句柄仍然会卡。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
