从网卡到 socket 排查 Linux 网络栈的丢包、重传与队列
一个包大致经过:网卡/驱动 → 内核协议栈(GRO、netfilter/conntrack、路由)→ qdisc → socket 接收队列 → 应用。排查时要先确定丢在哪一层,再选工具,而不是一上来就抓包。
ethtool -S、ip -s link 看 ring 丢包、CRC 和队列错误。nstat//proc/net/netstat 看重传、listen 溢出、连接跟踪;ss -tinm 看 socket 队列、RTT 和拥塞窗口。tc -s qdisc 看 qdisc 丢包和 backlog;net.core.netdev_max_backlog 控制入向 backlog。tcpdump/AF_PACKET 需要 root 或 CAP_NET_RAW;tc 和部分 ethtool 操作需要 CAP_NET_ADMIN;ss -p 看别人的进程需要 root。net.* sysctl;veth 对端和宿主机 qdisc 才是全局瓶颈所在。# 查看协议栈计数:重传、监听溢出、UDP 接收错误
nstat -az | grep -E 'TcpRetransSegs|TcpExtListenOverflows|TcpExtListenDrops|UdpRcvbufErrors'
# 查看 socket 队列、拥塞窗口和重传信息(-i 内部信息,-m 内存,-n 数字)
ss -tinm
# 查看网卡队列与驱动丢包计数
ethtool -S eth0 | grep -iE 'drop|miss|error|no_buffer'
ip -s link show eth0
# 查看 qdisc 排队、丢包和 backlog
tc -s qdisc show dev eth0
# 只抓 SYN/RST,减少抓包量和隐私数据
sudo tcpdump -ni eth0 -c 200 'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0'
# 检查常见内核网络参数
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog net.ipv4.tcp_congestion_control
ethtool -K <dev> tso off gso off 关闭后再判断。ethtool -S 的 miss/no_buffer)、backlog(nstat)、socket 队列(ss 的 Recv-Q)、应用不读,处理方式完全不同。ss 中 LISTEN 状态的 Send-Q 是 listen backlog,Recv-Q 是当前已完成握手的队列,不是数据字节数。dmesg 出现 nf_conntrack: table full, dropping packet 时调 nf_conntrack_max 或缩短超时。net.core.rmem_max 不够:tcp_rmem 的上限和应用 SO_RCVBUF 也要匹配,否则自动调优仍受限制。net.* 通常只影响自己的 net namespace;宿主机上的 veth、qdisc、conntrack 需要在宿主机排查。SO_REUSEPORT 才能用满多队列。ethtool -S 的 ring miss/no_buffer、nstat 的 backlog 丢弃计数、ss 的 Recv-Q 与应用读取速度。