Linux怎么配置系统的最大半连接数
TCP半连接队列由tcp_max_syn_backlog控制,与全连接队列somaxconn不同。调优需对齐tcp_max_syn_backlog、somaxconn及应用层backlog,注意tcp_syncookies会掩盖溢出。通过修改/etc/sysctl.conf并检查listenoverflows。
先说一个容易被忽略但又至关重要的细节:TCP 三次握手中,服务端收到 SYN 之后、还没等到 ACK 的那段“悬空”状态,其实藏着不少性能瓶颈。很多人在调优服务器时,只知道改 net.core.somaxconn,却忽略了半连接队列本身——结果就是高并发下客户端频频超时,服务端却一脸无辜。今天就把这块彻底说清楚。

什么是半连接(SYN Queue)?
半连接不是“已建立的连接”,而是 TCP 三次握手中,服务端收到 SYN 包、发送 SYN+ACK 后、尚未收到客户端 ACK 的中间状态。这些未完成握手的连接被暂存在内核的 syn queue(也叫 SYN backlog),其长度由 net.ipv4.tcp_max_syn_backlog 控制。它和 net.core.somaxconn(全连接队列上限)常被混淆,但二者作用不同:前者管“握手中的请求”,后者管“已完成握手、等待 accept() 的连接”。
怎么查当前半连接队列大小?
直接读内核参数:
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
常见默认值是 128 或 256(取决于内核版本和内存大小)。这个值太小会导致高并发短连接场景下 SYN 包被丢弃,表现为客户端超时或重传,服务端却看不到新连接进 ss -s 或 netstat -s | grep -i "listen overflows" —— 后者出现 “listen overflows” 就是半连接队列溢出的明确信号。
如何永久增大半连接队列?
修改 /etc/sysctl.conf,添加或调整这一行:
net.ipv4.tcp_max_syn_backlog = 65535
然后执行:
sudo sysctl -p
注意三点:
tcp_max_syn_backlog值不能超过net.core.somaxconn,否则实际生效值会被截断为后者;所以务必先确认并同步调大net.core.somaxconn- 某些内核(如较新版本)会根据内存自动计算该值,手动设置后需验证是否真正写入:
sysctl net.ipv4.tcp_max_syn_backlog - 应用层监听 socket 的
backlog参数(如listen(fd, backlog)中的backlog)必须 ≤tcp_max_syn_backlog,否则内核会静默截断——很多 Go/Python 服务默认用 128,远低于调优后的系统值,得同步改代码或启动参数
为什么调了还是溢出?容易忽略的点
半连接队列溢出不只看单个参数。以下情况会让配置“看似生效实则无效”:
- 没关
net.ipv4.tcp_syncookies:设为1(默认开启)时,内核在队列满时会启用 cookie 机制伪造 SYN+ACK,掩盖溢出问题,但会增加延迟和 CPU 开销;若要真实压测队列容量,可临时关掉:echo 0 > /proc/sys/net/ipv4/tcp_syncookies - 服务监听时用了过小的
backlog值:比如 Nginx 默认listen ... backlog=511,而系统设了 65535,但 511 仍远小于它;需在nginx.conf的listen指令里显式加backlog=65535 net.core.somaxconn过低:它既是全连接队列上限,也间接约束半连接队列最大值;建议至少设为相同量级,例如都设成65535
真正有效的半连接调优,是 tcp_max_syn_backlog、somaxconn、应用层 backlog 三者对齐,且关闭 syncookie 干扰后实测 listen overflows 计数不再增长。


































