只改net.core.somaxconn可能无效,因其实际生效值为min(backlog参数, somaxconn),需同步调高应用层listen的backlog值并重启服务,否则队列仍被卡在低水平。

调高 net.core.somaxconn 是解决高并发下“Connection refused”或“listen queue overflow”的关键一步,但单改它往往不够——必须同步协调内核、协议栈和应用层三者,否则实际生效值仍被卡在低水平。
为什么只改 somaxconn 还可能无效
这个参数控制的是每个监听 socket 的全连接队列(accept 队列)上限,即已完成三次握手、等待应用 accept() 的连接数。但它不是孤立起作用的:
- 内核最终取
min(backlog 参数, net.core.somaxconn)作为实际队列长度 - 如果应用调用
listen(fd, 128),哪怕somaxconn=65535,队列仍卡在 128 - 部分语言/框架有默认值:Tomcat acceptCount=100、Nginx 默认 backlog=511、旧版 Go 默认用系统 SOMAXCONN 值但不显式透出
怎么确认当前队列是否真溢出了
别只看错误日志,要查真实指标:
- 运行
ss -ltn,观察目标端口的 Send-Q 列——它显示的就是当前生效的全连接队列上限 - 执行
netstat -s | grep -i "listen overflows",若数值持续增长,说明队列确实在丢连接 - 检查 uWSGI 或 Nginx 错误日志里是否有 "listen queue of socket X full" 或 "upstream timed out"
标准调优操作步骤
三步必须连做,缺一不可:
-
调内核参数:临时执行
sysctl -w net.core.somaxconn=65535;永久生效则写入/etc/sysctl.conf并运行sysctl -p -
改应用配置:Tomcat 调
acceptCount,Nginx 在listen指令后加backlog=65535,uWSGI 启动加--listen 65535,Node.js 用server.listen(port, host, 65535) - 重启服务:修改后必须重启对应服务进程,否则新 backlog 不会加载进 socket
顺带检查半连接队列(防 SYN_RECV 堆积)
全连接队列扩容后,半连接队列(SYN 队列)可能成为新瓶颈:
- 运行
sysctl net.ipv4.tcp_max_syn_backlog net.core.somaxconn,确保两者设为相同值(如都 65535) - 检查
ss -ntp state syn-recv | wc -l,若长期 >100,说明半连接堆积,需同步调大上述两个参数 - 验证半连接丢包:用
awk '/^TcpExt/ {print $1,$2}' /proc/net/snmp | grep SynsToListenDrops,该值上升快即表示 SYN 被内核直接丢弃











