2、网络层瓶颈诊断:网络延迟构成与调优实战
网络层的问题,说实话,是交易系统里最难定位的一类。为什么?因为它的症状往往跟应用层很像——用户觉得慢、订单卡住、行情延迟。但查了一圈代码,发现逻辑没问题。这时候,十有八九是网络在搞鬼。
我个人习惯,遇到性能问题先看网络。不是因为我偏爱网络层,而是因为网络问题一旦出现,影响面特别大。一个交换机跳数多了,整个机房的延迟都受影响。好,我们直接进入正题。
2.1 网络延迟的三大构成
网络延迟不是单一概念。它由三部分组成,我习惯叫它「延迟三兄弟」。
| 延迟类型 | 典型值(同城机房) | 影响因素 |
|---|---|---|
| 物理距离延迟 | 0.5ms - 2ms | 光纤长度、光速极限 |
| 交换机跳数延迟 | 每跳约 10μs - 50μs | 交换机处理能力、队列深度 |
| TCP 握手延迟 | 1 RTT(约 0.5ms - 2ms) | 三次握手、拥塞控制 |
物理距离延迟,说白了就是光在光纤里跑的时间。光速是 30 万公里/秒,但在光纤里实际只有约 20 万公里/秒。两地相距 100 公里,光跑一个来回就要 1ms。这个你改不了,只能通过机房选址来优化。
交换机跳数延迟,这个我踩过坑。有一次交易系统延迟突然从 1ms 飙到 3ms,查了半天发现是网络拓扑调整后,数据流多绕了两台交换机。每跳增加 30μs,看起来不多,但累积起来就很可观了。我建议,核心交易链路的交换机跳数控制在 3 跳以内。
TCP 握手延迟,这个最容易被忽视。很多交易系统用的是长连接,但行情订阅、订单回执这些短连接场景,每次都要三次握手。一个 RTT 就是 1ms,高频场景下这个开销不能忍。解决方案?用连接池或者直接上 RDMA。
核心观点: 网络延迟优化,优先解决「能改的」。物理距离改不了,但跳数和握手方式可以改。
2.2 网卡软中断与 RPS/RFS 调优
网卡收包后,会触发硬中断。硬中断处理完,剩下的工作交给软中断(softirq)。问题来了——软中断默认只在 CPU 0 上跑。你想想看,所有网络包都挤在一个核上,其他核闲着,这不就成瓶颈了吗?
我在项目中遇到过,一台 32 核的机器,网卡软中断全压在 CPU 0 上,CPU 0 跑到 100%,其他核只有 20%。交易系统的吞吐量直接腰斩。怎么解决?用 RPS(Receive Packet Steering)和 RFS(Receive Flow Steering)。
RPS 的作用是把软中断分散到多个 CPU 上。配置方法很简单:
# 将网卡软中断分散到 CPU 0-3
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
# 查看当前 RPS 配置
cat /sys/class/net/eth0/queues/rx-0/rps_cpus
RFS 更进一步,它保证同一个 TCP 连接的数据包始终由同一个 CPU 处理。为什么重要?因为 CPU 缓存。同一个连接的数据包如果分散到不同核,缓存命中率会下降,反而更慢。
调优建议: RPS 的 CPU 掩码建议设置为物理核的一半。比如 32 核,用 0-15。不是越多越好,核数太多会导致缓存抖动。
我曾经在一个期货交易系统上做过测试。没开 RPS 前,软中断延迟的 P99 是 200μs。开了之后,降到了 50μs。效果立竿见影。
2.3 网络丢包与重传的排查
丢包和重传,是网络层最头疼的问题。症状很隐蔽——交易偶尔卡一下,但大部分时间正常。这种「间歇性抖动」最难定位。
我排查这类问题,一般分两步走:先用 netstat 看宏观指标,再用 tcpdump 抓微观包。
2.3.1 用 netstat 快速定位
# 查看网络统计信息
netstat -s | grep -E "retransmit|drop|loss"
# 重点关注这几个指标
# - retransmitted segments(重传段数)
# - TCPLostRetransmit(丢失的重传)
# - segments retransmited(注意拼写,原版就是少个 s)
如果重传率超过 0.1%,就要警惕了。我见过一个极端案例,重传率到了 5%,交易系统基本不可用。查下来是网线接触不良,换了根线就好了。嗯,有时候问题就这么简单。
注意: netstat 的 -s 参数显示的是累计值。要看实时趋势,建议用 watch -n 1 'netstat -s | grep retransmit' 持续观察。
2.3.2 用 tcpdump 抓微观包
netstat 告诉你「有问题」,但说不出「哪里有问题」。这时候上 tcpdump:
# 抓取交易服务器的网络包
tcpdump -i eth0 -s 0 -w /tmp/trade.pcap host 10.0.0.1 and port 8080
# 分析重传包
tcpdump -r /tmp/trade.pcap -nn -tt "tcp[tcpflags] & (tcp-syn|tcp-ack) != 0"
抓完包后,用 Wireshark 打开,重点看这几个东西:
- TCP Retransmission:标红的包,看是哪个方向在重传
- Duplicate ACK:连续三个重复 ACK,说明有丢包
- TCP Window Full:接收窗口满了,说明应用层处理不过来
我曾经排查过一个诡异的问题:交易系统每隔 30 秒卡一次。抓包发现是 ARP 广播导致的。交换机每 30 秒发一次 ARP 请求,网卡处理广播包时,正常的数据包被延迟了。解决方案?把 ARP 缓存超时时间调长,或者用静态 ARP。
避坑指南: 我曾经在排查丢包时,忽略了网卡自身的丢包计数器。用 ethtool -S eth0 | grep drop 看看,有时候丢包发生在网卡硬件层面,操作系统根本不知道。
2.4 知识体系总览
下面这张图,是我自己总结的网络层瓶颈诊断框架。每次排查问题,我都会对照着走一遍:
这张图的核心逻辑是:先理解延迟从哪来,再针对性地调优,最后用工具验证效果。三个环节缺一不可。
个人经验: 我建议每季度做一次网络层的「健康检查」。用 netstat 记录基线数据,用 tcpdump 抓一次典型交易的全链路包。这样出了问题,对比基线就能快速定位。
网络层的问题,说白了就是「快」和「稳」的平衡。RPS 开多了,延迟降了但 CPU 缓存命中率可能下降。TCP 参数调激进一点,吞吐量上去了但丢包风险增加。没有银弹,只有根据业务场景反复测试。
嗯,这一章的内容就到这里。记住,网络层的问题,80% 可以用 netstat 和 tcpdump 解决。剩下的 20%,需要你理解底层原理,结合业务场景去分析。
公众号:蓝海资料掘金营,微信deep3321