一、现象本质:为什么大量 SYN_RECV、正常用户连不上?
典型的: TCP 半连接队列被打满 / 被 SYN 泛洪攻击 / 高并发下 TCP 三次握手扛不住
流程一句话:
- 客户端发
SYN - 服务端回复
SYN+ACK,把连接放入 SYN 半连接队列 - 服务端等客户端
ACK,但一直等不到 - 半连接队列满 → 新连接直接被丢弃 → 正常用户 Connection Timeout
所以: 大量 SYN_RECV = 半连接队列溢出 = 新连接进不来
二、半连接队列到底会遇到什么问题?
半连接队列(SYN queue)核心风险就 3 个:
-
队列长度太小,高并发直接打爆 默认往往只有 128、256,流量一冲就满。
-
SYN Flood 攻击 攻击者海量发 SYN,不回 ACK,专门占满队列。
-
syncookies 没开 / 无效 内核不启用 syncookies,半连接队列一满就丢包。
结果统一表现:
netstat大量SYN_RECV- 正常用户连不上、超时
- 服务 CPU/内存不一定高,但就是不通
三、最快排查命令(直接复制用)
1. 看连接状态
netstat -ant | awk '{print $6}' | sort | uniq -c | sort -nr
或
ss -tan state syn-recv | wc -l
SYN_RECV 暴增 = 半连接队列满
2. 看半连接队列溢出统计
netstat -s | grep -i "syncookies"
netstat -s | grep -i "SYN"
出现:
times half-open connections droppedSYN cookies sent
说明 半连接队列已经在丢包了。
3. 看内核参数
sysctl net.ipv4.tcp_max_syn_backlog
sysctl net.ipv4.tcp_syncookies
sysctl net.core.somaxconn
这些值太小就是根源。
四、解决方案(线上直接生效)
1. 立刻打开 SYN Cookies(最关键)
sysctl -w net.ipv4.tcp_syncookies=1
作用: 半连接队列满时,不丢包,用 cookie 方式完成握手
2. 调大半连接队列
sysctl -w net.ipv4.tcp_max_syn_backlog=8192
高并发机器可以给到 16384 / 32768
3. 调大应用层全连接队列
sysctl -w net.core.somaxconn=8192
listen() 队列,和半连接队列配套。
4. 减少半连接超时重试(可选)
sysctl -w net.ipv4.tcp_synack_retries=2
默认 5 次,重试太久会占队列。
5. 持久化配置
echo "net.ipv4.tcp_syncookies = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 8192" >> /etc/sysctl.conf
echo "net.core.somaxconn = 8192" >> /etc/sysctl.conf
sysctl -p
五、高并发架构下的根因总结
遇到的 99% 是下面之一:
- 流量突增,半连接队列默认太小被打爆
- 被 SYN Flood 攻击
- tcp_syncookies=0,队列满直接丢包
- 客户端网络差,大量半连接 hanging
六、快速定位
- 看
SYN_RECV数量 → 确认半连接满 - 看
netstat -s→ 看是否丢半连接 - 开
tcp_syncookies→ 立刻缓解 - 调大
tcp_max_syn_backlog和somaxconn - 上 WAF/高防 → 防 SYN 攻击
注意:本文归作者所有,未经作者允许,不得转载