半连接队列上限是什么
net.ipv4.tcp_max_syn_backlog 限制半连接队列(也叫 SYN 队列)的容量。客户端发出 SYN、服务端回 SYN+ACK 但还没收到最终 ACK 时,这条连接排在半连接队列里,状态是 SYN_RECV。队列被填满后,新的 SYN 可能被直接丢弃,或者在启用 SYN Cookie 时改用无状态方式继续握手。它和全连接队列是两套独立结构:全连接队列由 net.core.somaxconn 与应用的 listen backlog 决定。
基本信息
| 参数 | net.ipv4.tcp_max_syn_backlog |
|---|---|
| 作用对象 | 半连接队列,即等待完成三次握手的请求 |
| 常见默认值 | 内核与发行版差异较大,常见 4096 级别,以本机回读为准 |
| 相关状态 | SYN_RECV 连接数量可反映队列占用 |
| 关联参数 | net.ipv4.tcp_syncookies 决定队列满时的处理方式 |
| 溢出计数 | /proc/net/netstat 中的 TCPReqQFullDrop 与 TCPReqQFullDoCookies |
典型使用场景
- 公网服务遭受 SYN 泛洪:靠它结合 SYN Cookie 撑过后端处理不过来的时段
- 高并发建连场景:短连接风暴下确认丢弃是发生在半连接还是全连接阶段
- 排查客户端超时:客户端 SYN 超时重传,服务端日志却看不到任何请求痕迹
- 容量评估:按峰值新建连接速率与握手完成时间估算所需的半连接队列深度
- 链路质量差的环境:高丢包或高延迟导致 ACK 回得慢,队列占用时间被拉长
查看与调整
查看与调整
sysctl net.ipv4.tcp_max_syn_backlog # 读当前上限
ss -lnt | head # Listen 行的 Send-Q 为应用申请的 backlog
ss -nt state syn-recv | wc -l # 当前处于半连接状态的条目数
nstat -az TcpExtTCPReqQFullDrop TcpExtTCPReqQFullDoCookies # 队列溢出计数
netstat -s | grep -i -E 'SYNs to LISTEN|overflow' # 老系统上的对应统计
sysctl -w net.ipv4.tcp_max_syn_backlog=8192 # 临时调大落盘与回读
落盘与回读
# /etc/sysctl.d/99-net-tuning.conf
net.ipv4.tcp_max_syn_backlog = 8192 # 抬高半连接队列上限
net.ipv4.tcp_syncookies = 1 # 队列满时用 SYN Cookie 兜底
# 回读命令:sysctl net.ipv4.tcp_max_syn_backlog溢出指标读法
| 指标 | 含义 | 正常与异常 |
|---|---|---|
| SYN_RECV 数量 | 半连接队列当前占用 | 短时波动正常,持续高位或持续增长需分析来源 |
| TCPReqQFullDrop | 队列满且未启 Cookie 导致的丢弃次数 | 持续增长说明握手请求被真实丢弃 |
| TCPReqQFullDoCookies | 队列满后改用 Cookie 的次数 | 增长说明队列确实触顶,但连接仍能完成 |
| ss 显示的应用 backlog | 应用侧申请值 | 与内核上限无关,两者取较小值决定全连接队列 |
现代内核里半连接队列的实际行为还受 SYN Cookie 与内部调整逻辑影响,单看这个数值不能完整判断是否溢出。判断依据应当是计数器的增长趋势与 SYN_RECV 的实际数量,而不是参数本身的大小。
SYN_RECV 状态本身是正常的过渡态,短暂出现几条十几条没有意义。真正需要关注的是数量级与增长趋势,以及是否伴随 TCPReqQFullDrop 这类丢弃计数。
半连接队列不是防御 SYN 泛洪的主力手段:把上限调得很大只是降低被填满的概率,攻击流量仍在消耗带宽与处理能力。公网服务更应依赖上游清洗、流量限速与连接速率限制。