事情本身不复杂,线索都在日志里。CentOS 7.9 上 nginx 前面没有负载均衡,压测到三千并发时有一小部分请求直接超时,nginx 日志里没有对应记录,netstat -s 的 listen overflows 每次压测都涨几百,somaxconn 已经调到 65535。
第一反应是「全连接队列受 somaxconn 和 listen backlog 双重限制,只改一个没用」,验证下来不成立。
原因不止一个,得分开看。nginx 自己 listen 的 backlog 没改,还是默认的 511,内核取两者中较小的。另一种情况是accept 跟不上,worker 被上游拖住,队列里的连接过期后被丢。
还有一种情况,SYN 队列溢出被当成全连接溢出,看错了计数器。
上来先确认到底是哪个计数器在涨
netstat -s | grep -iE 'listen|overflow|SYN'
再往下看 listen socket 当前的队列长度
ss -lnt | grep ':80'
接着确认配置里的 listen 有没有写 backlog
grep -rn 'listen 80' /etc/nginx/ && nginx -t
等前面都确认过,再核对内核侧的两个上限
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog
恢复的判定其实很直接。同样的并发再压一轮,listen overflows 不再增长,ss 里 Send-Q 的峰值低于设定值,请求超时比例降到零。
backlog 只是缓冲,accept 慢的根因通常在 worker 数量和上游耗时;队列调得很大反而让超时表现得更隐蔽,客户端要等更久才失败。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
