半连接溢出本质是服务端在三次握手第一阶段丢弃SYN包,导致客户端连接超时;需通过netstat、ss、dmesg验证,协同调大tcp_max_syn_backlog和somaxconn,启用SYN Cookie,并同步调整应用层backlog配置。

半连接溢出(SYN queue overflow)本质是服务端在三次握手第一阶段就丢弃了 SYN 包,客户端收不到响应,表现为“连接超时”或“首次请求失败”,但 netstat 或日志里却查不到明显错误。关键不是堆硬件,而是让内核队列容量、应用监听配置和业务流量节奏对齐。
确认是否真发生了半连接溢出
别猜,先验证:
- 运行
netstat -s | grep -i "listen overflows\|SYNs to LISTEN"—— 若数值非零且持续增长,说明已丢包 - 执行
ss -n state syn-recv | wc -l查当前半连接数,再对比cat /proc/sys/net/ipv4/tcp_max_syn_backlog(默认常为128或512) - 检查内核日志:
dmesg | grep -i "possible SYN flooding",出现该提示通常意味着队列满且未启用防护机制
调大两个核心队列参数
半连接队列和全连接队列必须协同调整,单边放大无效:
-
net.ipv4.tcp_max_syn_backlog:控制每个监听端口的半连接队列长度。建议设为峰值每秒 SYN 数的 1.5–2 倍(如突发 300/s,可设 512 或 1024) -
net.core.somaxconn:系统级全连接队列上限,也隐式约束半连接队列最大值。应 ≥tcp_max_syn_backlog,常见设为 2048 或 65535 - 临时生效:
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048和sudo sysctl -w net.core.somaxconn=2048 - 持久化:写入
/etc/sysctl.d/99-tcp-queue.conf,再运行sudo sysctl --system
开启 SYN Cookie 作为兜底防护
当突发远超预估时,SYN Cookie 能避免直接丢包,代价是轻微 CPU 开销且不支持 SACK 等高级选项:
- 启用:
sudo sysctl -w net.ipv4.tcp_syncookies=1 - 生产环境建议始终开启,尤其面向公网的服务
- 注意:它不是替代调参的方案,而是最后一道防线
同步调整应用层监听配置
内核参数再大,应用没配对也白搭。listen() 的 backlog 参数受 somaxconn 截断:
- Nginx:在
listen 80;后加backlog=2048 - Go:用
net.ListenConfig显式设置 socket backlog,不能只靠默认值 - Java(Tomcat):在
server.xml的 Connector 中设acceptCount="2048" - 检查当前应用实际生效值:
ss -ln | grep :端口,看 Recv-Q 列是否接近你设的值
从源头降低 SYN 压力
参数调优是治标,架构优化才是治本:
- 前端加反向代理(如 Nginx),开启
keepalive复用连接,把千次短连压成几十条长连 - 排查异常客户端:健康检查频率过高、移动端弱网重试风暴、扫描器探测等,可用
iptables限速初步识别 - 避免在服务端做无意义的 TCP 探活,改用更轻量的应用层心跳











