网络延迟的根源:物理距离、传输介质、协议开销、操作系统调度、中断处理

做网络优化这么多年,我见过太多人一上来就调内核参数、改网卡配置,结果延迟还是降不下来。为什么?因为根本没搞清楚延迟到底从哪来的。

网络延迟不是单一问题。它是多个环节叠加的结果。我习惯把延迟拆成五个层面来看:物理层、链路层、协议层、系统层、硬件层。每个层面都有它的坑。

核心观点:延迟优化,先定位根源,再动手。定位错了,优化就是瞎忙活。

物理距离:光速也救不了你

先说最基础的。信号在光纤里跑,速度大约是光速的2/3,也就是每秒20万公里左右。北京到上海1300公里,单程延迟大约6.5毫秒。这还没算中间设备的转发时间。

我曾经帮一家金融客户做交易系统优化。他们发现北京到深圳的交易延迟比预期高了10毫秒。查了半天,发现数据绕道香港走了一圈。说白了,物理路径没选对。

为什么会这样?很多公司租用运营商线路时,只关注带宽,不关注路由。结果数据包可能绕了大半个中国才到目的地。

距离 理论最小延迟(光纤) 实际典型延迟
同机房(1米) 0.005 μs 0.1-0.5 ms
同城(50km) 0.25 ms 1-3 ms
跨省(1000km) 5 ms 10-30 ms
跨洋(10000km) 50 ms 100-300 ms

避坑指南:我曾经见过一个团队把核心数据库部署在美西,用户全在亚洲。每次查询延迟200多毫秒。后来迁移到新加坡,延迟降到30毫秒。物理距离这个坑,一开始就要避开。

传输介质:铜缆、光纤、无线,差别很大

传输介质直接影响信号传播速度和抗干扰能力。铜缆(比如Cat6网线)信号传播速度大约是光速的0.7倍。光纤能到0.67倍。无线信号在空气中接近光速,但受干扰严重。

你想想看,数据中心内部为什么都用光纤?不是因为带宽大,而是因为延迟低、干扰小。我做过一个测试:同样100米距离,Cat6网线延迟比光纤高了约0.3微秒。单看不大,但累积起来就明显了。

嗯,这里要注意:无线网络虽然传播速度快,但碰撞检测、重传机制会引入额外延迟。我建议关键业务别走无线,除非你做好了重传容忍的准备。

协议开销:TCP的慢启动和三次握手

协议开销是很多人忽略的延迟来源。TCP协议为了保证可靠性,做了很多额外工作。三次握手、慢启动、拥塞控制,每一步都在增加延迟。

我记得有一次帮一个视频直播平台做优化。他们用TCP传输视频流,延迟一直在200毫秒以上。我建议换成UDP加自定义重传逻辑,延迟直接降到50毫秒以下。

为什么会这样?TCP的三次握手需要1.5个RTT(往返时间)。如果RTT是100毫秒,光握手就150毫秒没了。再加上慢启动,前几个数据包根本跑不满带宽。

// TCP三次握手延迟示例
// 客户端 -> SYN -> 服务器 (RTT/2)
// 服务器 -> SYN-ACK -> 客户端 (RTT/2)
// 客户端 -> ACK -> 服务器 (RTT/2)
// 总延迟:1.5 * RTT

// 如果RTT = 100ms
// 握手延迟 = 150ms
// 这还没开始传数据呢

关键点:协议开销是软件层面的延迟。选对协议,比调优参数更有效。低延迟场景,我倾向用UDP或RDMA。

操作系统调度:上下文切换的代价

操作系统调度是隐藏的延迟杀手。每次上下文切换,CPU要保存当前任务状态,加载新任务状态。这个过程需要几十微秒到几百微秒。

你想想看,一个网络数据包到达网卡,需要经过中断处理、内核协议栈、用户态应用。每一步都可能触发调度。如果系统负载高,调度延迟会急剧增加。

我曾经优化过一个高频交易系统。发现系统在负载高时,网络延迟从10微秒飙升到500微秒。查了半天,是内核的CFS调度器在抢CPU时间。后来绑核、设置实时优先级,才把延迟稳定下来。

调度场景 典型延迟 优化方法
普通进程调度 10-100 μs 绑核、设置优先级
中断处理 1-10 μs 中断合并、多队列
系统调用 0.1-1 μs 使用DPDK绕过内核

警告:不要盲目调优内核参数。我曾经见过有人把内核抢占模式改成完全抢占,结果系统稳定性下降,反而增加了延迟。调优前先做基准测试。

中断处理:网卡中断的连锁反应

中断处理是硬件和软件的交界点。网卡收到数据包后,会触发中断通知CPU。CPU暂停当前工作,处理中断。这个过程看似简单,但问题很多。

首先,中断频率太高会引发中断风暴。一个万兆网卡每秒能收1500万个数据包,如果每个包都触发中断,CPU就光处理中断了,啥也干不了。

其次,中断处理过程中,CPU的缓存会被污染。我之前做过测试:一次中断处理,L1缓存命中率下降约30%。这意味着后续指令执行变慢。

我建议的做法是:使用中断合并(NAPI)和多队列(RSS)。中断合并让网卡攒一批数据包再通知CPU,减少中断次数。多队列让不同CPU处理不同队列,避免单核瓶颈。

// 中断合并配置示例(ethtool)
// 查看当前中断合并参数
ethtool -c eth0

// 设置中断合并
// rx-usecs: 接收中断延迟(微秒)
// rx-frames: 接收中断触发帧数
ethtool -C eth0 rx-usecs 50 rx-frames 8

// 设置RSS多队列
ethtool -L eth0 combined 4

个人经验:中断合并不是越大越好。合并时间太长,单个数据包延迟会增加。我一般从10微秒开始调,逐步增加,找到延迟和吞吐量的平衡点。

知识体系总览

下面这张图总结了网络延迟的五个根源,以及它们之间的关系。你可以把它当作排查问题的路线图。

网络延迟根源分析框架 物理距离 传输介质 协议开销 操作系统调度 中断处理 延迟逐层叠加 光速限制、路由绕行 铜缆/光纤/无线差异 三次握手、慢启动、拥塞控制 上下文切换、优先级 中断风暴、缓存污染 优化方向 • 物理层:选择最近的数据中心、优化路由路径 • 链路层:使用光纤替代铜缆、减少无线干扰 • 协议层:UDP替代TCP、使用RDMA、优化窗口大小 • 系统层:绑核、设置实时优先级、使用DPDK • 硬件层:中断合并、多队列、硬件卸载 定位根源 → 选择优化方向 → 验证效果

这张图把五个延迟根源和对应的优化方向串起来了。你排查问题时,可以按这个框架一层层往下查。物理距离不对,调内核参数也没用。协议选错了,换网卡也白搭。

嗯,最后说一句:延迟优化没有银弹。每个场景的瓶颈都不一样。我见过有人花几周调内核参数,结果发现是网线没插好。所以,先定位,再动手。