真实吞吐量应以应用层实际送达数据量为准,需用 iperf3 测端到端 TCP 吞吐、ss -i 查重传与 RTT、tcpdump + tshark 算有效载荷;延迟需分网络层(mtr)、TCP 建连(curl -w)、应用层(tcpdump 时间戳)三类评估。

怎么看真实吞吐量:别只信 ifconfig 或 ip -s link
网卡统计的 tx_bytes / rx_bytes 是底层收发 字节 数,包含重传、校验失败、驱动丢包等噪声,不能直接当有效吞吐。真实吞吐得看应用层实际送达的数据量。
推荐组合验证:
- 用
iperf3 -c server -t 30 -P 4测端到端 TCP 吞吐,-P并发数要匹配业务模型(单流 vs 多连接) - 同时跑
ss -i查单条连接的retransmits和rcv_rtt,若重传率 > 1%,说明链路或接收端有瓶颈 - 抓包比对:
tcpdump -i eth0 'host target' -w cap.pcap+tshark -r cap.pcap -qz io,stat,1,"SUM(tcp.len)"算每秒有效载荷
延迟不是 ping 一下就完事:区分三类延迟场景
ping 只测 ICMP echo 的往返,对 TCP 业务参考价值有限。关键要分清:
- 网络层延迟 :用
mtr --report target看每跳 RTT 分布,识别 路由 抖动或中间设备排队 - TCP 建连延迟:
curl -w "@curl-format.txt" -o /dev/null -s http://target中%{time_connect}暴露 SYN/SYN-ACK 往返耗时 - 应用层处理延迟 :在服务端用
tcpdump标记请求到达与响应发出时间戳,排除内核协议 栈之外的排队(如 nginx worker 队列、DB 查询)
netstat 和 ss 看连接状态,但真正卡住的是队列
大量 ESTABLISHED 不代表健康;要看接收 / 发送队列是否堆积:
ss -tin | awk '$1 ~ /^tcp/ && ($2+$3> 0) {print $1,$4,$5,$2,$3}'
输出中第 4 列是 recv-q(内核接收队列未被应用读走的字节),第 5 列是 send-q(应用写入但未被对端 ACK 的字节)。持续 > 0 说明:
-
recv-q高 → 应用读取慢(如 Pythonsocket.recv()阻塞、GC 暂停)或缓冲区太小(net.core.rmem_default) -
send-q高 → 对端接收窗口缩为 0,或本端拥塞控制降速(查ss -i中cwnd和ssthresh)
内核参数调优不是堆数字:先确认瓶颈类型再动 /proc/sys/net/
盲目改 net.ipv4.tcp_tw_reuse 或 net.core.somaxconn 可能掩盖真实问题。优先检查:
- 是否触发了
ListenOverflows?netstat -s | grep -i "listen.*over"非零表示 SYN 队列溢出,此时才调net.core.somaxconn和应用backlog - 是否大量
TIME_WAIT占用 端口?用ss -tan state time-wait | wc -l统计,仅当短连接密集且端口耗尽时才考虑tcp_tw_reuse(注意:仅客户端生效) - 是否因
net.ipv4.tcp_slow_start_after_idle=0导致长连接吞吐下降?Linux 4.1+ 默认关闭慢启动空闲重置,旧内核需手动关
所有调整必须配合压测对比,比如改完 net.core.rmem_max 后,用 ss -i 观察 rcv_space 是否真正提升,而不是只看 sysctl 值。