网络延迟的根源:物理距离、传输介质、协议开销、操作系统调度、中断处理
做网络优化这么多年,我见过太多人一上来就调内核参数、改网卡配置,结果延迟还是降不下来。为什么?因为根本没搞清楚延迟到底从哪来的。
网络延迟不是单一问题。它是多个环节叠加的结果。我习惯把延迟拆成五个层面来看:物理层、链路层、协议层、系统层、硬件层。每个层面都有它的坑。
核心观点:延迟优化,先定位根源,再动手。定位错了,优化就是瞎忙活。
物理距离:光速也救不了你
先说最基础的。信号在光纤里跑,速度大约是光速的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微秒开始调,逐步增加,找到延迟和吞吐量的平衡点。
知识体系总览
下面这张图总结了网络延迟的五个根源,以及它们之间的关系。你可以把它当作排查问题的路线图。
这张图把五个延迟根源和对应的优化方向串起来了。你排查问题时,可以按这个框架一层层往下查。物理距离不对,调内核参数也没用。协议选错了,换网卡也白搭。
嗯,最后说一句:延迟优化没有银弹。每个场景的瓶颈都不一样。我见过有人花几周调内核参数,结果发现是网线没插好。所以,先定位,再动手。