ss命令中Recv-Q/Send-Q含义依连接状态而异:LISTEN时,Recv-Q为全连接队列当前长度,Send-Q为其上限;ESTAB时,Recv-Q为接收缓冲区未读字节数,Send-Q为已发未确认字节数。

Linux里没有一个叫“系统Socket队列长度”的全局统一值——它分好几层,每层查法不同、含义也完全不同。直接用 ss 看 Recv-Q/Send-Q 是最常用且有效的起点,但得知道它对应哪一层。
怎么用 ss 查单个 socket 的当前队列长度
ss -tlnp 或 ss -tunp 能看到每个监听或已连接 socket 的实时队列水位,关键看 Recv-Q 和 Send-Q 两列:
-
Recv-Q:对LISTEN状态 socket,是 accept 队列里已三次握手完成、等待被accept()取走的连接数;对ESTAB状态,是内核接收缓存里还没被应用recv()拿走的字节数 -
Send-Q:对LISTEN状态无意义(固定为 0);对ESTAB状态,是发送缓冲区里还没被协议栈发出去的字节数(即sk_wmem_alloc的近似体现) - 如果
Recv-Q在LISTEN行长期 > 0,说明应用调用accept()不够快,accept 队列开始积压 - 如果
Send-Q在ESTAB行持续不为 0 且增长,可能是对端接收慢、网络卡顿,或本端应用写得太猛没控制节奏
怎么查全连接队列(accept queue)的最大长度
这个上限由内核参数 net.core.somaxconn 控制,但实际生效值取 listen(sockfd, backlog) 传入值和该参数的较小者:
- 查当前系统级上限:
cat /proc/sys/net/core/somaxconn - 查某个进程 listen 时传的
backlog值:需看源码或用strace -e trace=listen -p PID捕获(生产环境慎用) - 临时调大上限:
echo 65535 > /proc/sys/net/core/somaxconn,然后记得写入/etc/sysctl.d/99-socket.conf并运行sysctl --system - 注意:改完
somaxconn后,老的监听 socket 不会自动扩容,必须重启服务进程才能让新listen()生效
怎么查半连接队列(SYN queue)大小和限制
SYN queue 不暴露给用户态直接查看,但可通过间接指标判断是否溢出:
- 查当前设置:
cat /proc/sys/net/ipv4/tcp_max_syn_backlog(仅当net.ipv4.tcp_syncookies = 0时生效) - 关键观测点:
netstat -s | grep -i "syn"或ss -s输出里的SYNs to LISTEN sockets dropped计数——只要这个数在涨,就说明 SYN queue 溢出了 - 如果服务器暴露在公网且有扫描或攻击,
tcp_syncookies = 1是更稳妥的选择,此时 SYN queue 大小逻辑不同,不再依赖tcp_max_syn_backlog - 虚拟机或容器环境下,有些网络栈实现(如 eBPF-based)可能绕过传统 SYN queue,
ss -s的统计未必完全反映真实丢包路径
为什么不能只看 ifconfig 或 ip link 的 txqueuelen
txqueuelen 是网卡驱动层的发送队列长度,和 socket 层的 Send-Q 完全不是一回事:
-
ip link show eth0里的txqlen控制的是“协议栈交给驱动后、还没进网卡 Ring Buffer 的包最多能缓多少”,单位是包数,不是字节 - 而
ss的Send-Q是 socket 发送缓冲区剩余字节数,属于传输层,受SO_SNDBUF、拥塞窗口、对端接收窗口等共同影响 - 两者之间隔着 TCP 栈、SKB 分配、GSO/GRO、驱动队列、Ring Buffer 多层——某一层堵了,上层队列都会涨,但原因完全不同
- 常见误操作:看到
Send-Q高就去调txqueuelen,结果毫无改善,因为瓶颈其实在软中断处理不过来,或 CPU 被占满
真正难的不是查哪个数字,而是把 ss 的队列水位、/proc/net/snmp 的 TCP 统计、/proc/interrupts 的软中断分布、以及应用日志里的超时和重试串起来看——队列长度只是症状,不是病因。


















