在 Linux 网络编程中,backlog 溢出通常是指 TCP 监听 socket 的 accept 队列(全连接队列)或 syn 队列(半连接队列)溢出,导致新连接被丢弃或重置。下面从原理到常见原因系统说明。
对于 listen(fd, backlog):
backlog 主要指 全连接队列(accept queue)最大长度min(backlog, /proc/sys/net/core/somaxconn)相关队列:
客户端 SYN
↓
SYN队列(半连接)
↓
三次握手完成
↓
accept队列(全连接,backlog限制)
↓
accept() 取走
现象
accept()原因
表现
netstat -s | grep listentimes the listen queue of a socket overflowed
ss -lnt 中 Recv-Q 接近 Send-Q原因
net.ipv4.tcp_max_syn_backlog 太小表现
netstat -s 中:SYN cookies sent
listen(fd, 5); // 太小
即使系统支持大队列,也被限制。
解决
sysctl -w net.core.somaxconn=4096
listen(fd, 4096);
虽然不是“队列溢出”,但表现类似:
EMFILEaccept() 失败检查:
ulimit -n
cat /proc/sys/fs/file-max
fork 后各自 acceptSO_REUSEPORT 配置不当netstat -s | grep -i listen
ss -lnt
State Recv-Q Send-Q Local Address:Port
LISTEN 128 128 0.0.0.0:80
Recv-Q:当前全连接数Send-Q:backlog 上限cat /proc/net/netstat | grep TcpExt
关注:
ListenOverflowsListenDropsTCPBacklogDropnet.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_syncookies = 1
listen(fd, 65535);
backlog 溢出本质是:连接到达速度 > 应用 accept 速度 或 系统队列容量不足。
如果你愿意,可以告诉我:
我可以帮你做针对性分析。