网络时延与抖动:RTT、单向时延、抖动定义、抖动对多媒体播放的影响、如何测量时延
大家好,我是你们这节课程的讲师。咱们今天聊点实在的——网络时延和抖动。做流媒体传输,这两个东西要是搞不明白,那调试起来就像在黑暗里找开关,全靠运气。
我记得刚入行那会儿,有个项目播放器总是卡顿,我盯着带宽和丢包率看了三天,死活找不到原因。后来一位老大哥过来看了一眼,说:“你测过抖动吗?” 一句话点醒梦中人。从那以后,我养成了一个习惯:任何流控调试,先看时延和抖动。
RTT:往返时间
RTT,全称 Round-Trip Time,往返时间。说白了,就是你的数据包从 A 点跑到 B 点,再跑回来的总耗时。
举个例子。你给朋友发一条,他秒回。从你按下发送键,到你收到回复,这个时间差就是 RTT。在网络里,RTT 通常包含四部分:
- 发送端处理时延:数据包从应用层到网卡的时间
- 传输时延:光速在物理介质上跑的时间
- 排队时延:在路由器、交换机里排队等待转发的时间
- 接收端处理时延:对端网卡到应用层的时间
这里面,排队时延是最不稳定的。网络一拥堵,排队时间就暴涨,RTT 也跟着飙升。
关键点:RTT 是双向的,它包含了接收端处理的时间。所以 RTT 小,不一定代表单向时延也小。
单向时延:更真实的延迟指标
单向时延,就是数据包从发送端到接收端的单程时间。为什么说它更真实?因为多媒体流是单向的。你推流,观众看,数据只走一个方向。
但单向时延很难精确测量。为什么?因为发送端和接收端的时钟很难完全同步。你想想看,两台电脑的系统时间差个几毫秒,测出来的单向时延就全偏了。
我在项目中遇到过这种情况:RTT 只有 20ms,看起来网络很好,但播放端就是延迟高。后来用 NTP 同步了两端时钟,一测单向时延,好家伙,15ms。RTT 的一半是 10ms,这多出来的 5ms 就是接收端处理耗时。嗯,问题出在对端解码器上。
| 指标 | 含义 | 测量难度 | 对多媒体影响 |
|---|---|---|---|
| RTT | 数据往返总耗时 | 低(ping 即可) | 间接影响,用于估算 |
| 单向时延 | 数据单程传输耗时 | 高(需时钟同步) | 直接影响播放延迟 |
抖动:网络的不稳定因子
抖动,英文叫 Jitter。它描述的是时延的变化程度。不是时延本身,而是时延的波动。
举个例子。你连续发了 10 个包,RTT 分别是:20ms、22ms、19ms、21ms、50ms、20ms、21ms、19ms、22ms、20ms。看到第 5 个包了吗?突然跳到 50ms。这个波动,就是抖动。
抖动的计算公式很简单:
Jitter = |D(i-1, i) - D(i, i+1)|
其中 D(i, j) 是包 i 和包 j 的时延差
实际工程中,我们通常用滑动窗口计算平均抖动。比如每收到 100 个包,计算一次平均抖动值。
我的习惯:在流媒体服务器里,我会同时记录 RTT 和抖动。如果 RTT 高但抖动低,说明网络稳定只是距离远;如果 RTT 低但抖动高,那才是真正的麻烦——网络不稳定,缓冲区再大也救不了。
抖动对多媒体播放的影响
这才是咱们这节的核心。抖动为什么可怕?因为它直接破坏播放的连续性。
你想想看,播放器的工作方式是:从网络收数据,放进缓冲区,然后按固定间隔从缓冲区取数据解码显示。如果网络时延稳定,缓冲区水位就稳定,播放就流畅。
但抖动一来,数据到达的时间忽快忽慢。缓冲区水位就像过山车:
- 抖动导致缓冲区下溢:数据来晚了,缓冲区空了,播放器没数据可播,卡顿。
- 抖动导致缓冲区上溢:数据突然涌来,缓冲区满了,新数据被丢弃,花屏或跳帧。
我在项目中遇到过最典型的场景:一个直播平台,观众反馈画面每隔几秒就卡一下。我一看监控,RTT 只有 30ms,丢包率 0.1%,带宽也够。但抖动曲线显示,每 3-5 秒就有一个 40ms 的抖动尖峰。后来查出来是 CDN 边缘节点在做缓存刷新,导致路由短暂变化。
避坑指南:我曾经犯过一个错误——只关注平均抖动,忽略了峰值抖动。平均抖动 5ms 看起来很漂亮,但峰值抖动 100ms 才是卡顿的元凶。现在我的监控面板上,抖动峰值和抖动 95 分位值是必看的指标。
如何测量时延
测量方法分两种:主动测量和被动测量。
主动测量
主动发探测包,计算时延。最常用的工具就是 ping。
# 测量 RTT
ping -c 10 192.168.1.1
# 输出示例
rtt min/avg/max/mdev = 18.432/20.123/25.678/2.345 ms
这里的 mdev 就是抖动(标准偏差)。但 ping 只能测 RTT,测不了单向时延。
要测单向时延,需要两端配合。我常用的方法是:
- 两端用 NTP 同步时钟
- 发送端在数据包里打时间戳 T1
- 接收端收到后记录时间 T2
- 单向时延 = T2 - T1
被动测量
不额外发探测包,直接从数据流中提取时延信息。比如在 RTMP 或 SRT 协议里,数据包本身就携带时间戳。
以 SRT 协议为例,它的数据包里有:
- PktTsbpdTime:发送端时间戳
- PktRcvTime:接收端本地时间
两者相减,就是单向时延。SRT 还内置了抖动计算,直接通过 API 就能拿到。
实战建议:在 WebRTC 里,可以通过 RTCP Receiver Report 获取 RTT。具体做法是:发送端发 SR(Sender Report),接收端回 RR(Receiver Report),RR 里携带了 DLSR(Delay since Last SR),发送端用当前时间减去 DLSR 就能算出 RTT。
知识体系总览
下面这张图,是我自己梳理的时延与抖动知识框架。每次做流控调试,我都会对照这张图排查问题。
这张图把时延、RTT、单向时延、抖动以及它们的影响和测量方法串在了一起。你可以把它当作调试时的检查清单。
好了,这节的内容就到这儿。时延和抖动是流控调试的基石,搞懂了它们,后面讲拥塞控制和自适应码率的时候,你会觉得顺滑很多。记住我的一句话:先看抖动,再看时延,最后看带宽。这个顺序,是我踩了无数坑总结出来的。