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 知识体系总览

下面这张图,是我自己总结的网络层瓶颈诊断框架。每次排查问题,我都会对照着走一遍:

网络层瓶颈诊断框架 网络延迟三大构成 物理距离延迟 交换机跳数延迟 TCP握手延迟 网卡软中断调优 RPS:软中断分散到多核 RFS:同连接同核处理 丢包与重传排查 netstat -s:宏观统计 tcpdump + Wireshark:微观分析

这张图的核心逻辑是:先理解延迟从哪来,再针对性地调优,最后用工具验证效果。三个环节缺一不可。

个人经验: 我建议每季度做一次网络层的「健康检查」。用 netstat 记录基线数据,用 tcpdump 抓一次典型交易的全链路包。这样出了问题,对比基线就能快速定位。

网络层的问题,说白了就是「快」和「稳」的平衡。RPS 开多了,延迟降了但 CPU 缓存命中率可能下降。TCP 参数调激进一点,吞吐量上去了但丢包风险增加。没有银弹,只有根据业务场景反复测试。

嗯,这一章的内容就到这里。记住,网络层的问题,80% 可以用 netstat 和 tcpdump 解决。剩下的 20%,需要你理解底层原理,结合业务场景去分析。


公众号:蓝海资料掘金营,微信deep3321