TCP半连接队列是内核维护的SYN_RECV状态连接缓冲区,本质为哈希表结构,用于暂存已发SYN-ACK但未收到ACK的中间态连接;其长度由tcp_max_syn_backlog控制,受somaxconn截断,溢出时静默丢弃SYN包导致客户端超时。

Linux 中 TCP 半连接(SYN Queue)限制,本质是内核对“正在握手但尚未完成”的连接数的硬性管控。它不等于已建立连接,而是三次握手中服务端发完 SYN+ACK、等待客户端 ACK 的中间态队列。队列满会导致 SYN 包被静默丢弃,客户端表现为超时重传,服务端却无新连接日志——这是高并发场景下典型的“连接建立失败”根因。
半连接队列到底是什么
当客户端发起 SYN 请求,服务端分配 socket、进入 SYN_RECV 状态,并将该连接放入半连接队列;收到对应 ACK 后,才移出该队列、转入全连接队列。这个过程完全由内核网络栈处理,应用层无感知。队列底层是哈希表结构(非链表),用于快速查找和管理大量未完成握手请求。
- 状态标识:所有在队列中的连接,netstat 或 ss 显示为 SYN_RECV
- 生命周期短:通常几秒内完成或超时释放(受 tcp_synack_retries 控制)
- 资源开销:每个半连接占用约 256 字节内存,总大小受可用内存约束
关键参数与默认值
控制半连接队列长度的核心参数是 net.ipv4.tcp_max_syn_backlog,它定义每个监听 socket 的最大半连接数。该值不是全局统一,而是按监听端口独立生效。
- 常见默认值:128、256 或 1024,取决于内核版本和系统内存容量
- 查看当前值:cat /proc/sys/net/ipv4/tcp_max_syn_backlog
- 注意:若 net.core.somaxconn 设置过小(如仍为默认 128),部分旧内核会以此值为上限截断 tcp_max_syn_backlog
怎么判断队列是否溢出
不能只看 SYN_RECV 数量,要结合内核统计和日志交叉验证。溢出不是错误,而是主动丢包的保护行为。
- 查丢包证据:netstat -s | grep -i "listen overflows" —— 数值增长即确认溢出
- 看实时堆积:ss -n state syn-recv | wc -l,对比 tcp_max_syn_backlog 值
- 查防护触发:dmesg | grep -i "possible SYN flooding",说明队列满且 syncookies 未启用
调优建议与注意事项
调大参数只是缓解手段,需配合业务特征和架构设计,避免盲目堆数值。
- 设值参考:按峰值每秒 SYN 请求数 × 1.5~2,例如突发 300/s,可设为 512 或 1024
- 配套调整:net.core.somaxconn ≥ tcp_max_syn_backlog,建议统一设为 1024 或 2048
- 必开开关:net.ipv4.tcp_syncookies = 1,队列满时自动启用 Cookie 机制,防止大面积丢包
- 慎用操作:修改后需重启监听进程(如 Nginx、Java 应用)才能使新 backlog 生效,仅改内核参数不够


















