设想这样一个晚上:电脑在下载大文件,速度很漂亮。你拿起手机想回条消息,图片转了半天;打开网页,也比平时慢。把下载暂停,其他操作很快又顺了。
看起来是下载“抢走了网速”。但还有一个疑问:发条消息才多少数据,难道连这么一点空隙都没有?
问题可能就出在等待上。出口一直有数据通过,后来的小请求却排在长队里。下载统计的是每秒送走多少数据,用户感受到的则是自己的请求等了多久。
这篇聊的,就是网络忙起来以后产生的排队。它不是所有卡顿的解释,但很适合用来理解“一开大任务,别的都难用”这类现象。
下载速度很高,与网页响应很慢,可以同时发生
收银台一直忙着结账,每分钟处理的商品很多,不代表刚进队的人能马上结完账。
大文件下载与打开网页,也可能遇到类似的差别。
下载已经建立连接,持续接收数据,只要传输没有停,速度数字就可能很好看。新打开的网页却要发出请求、等到响应,某些资源还需要等前面的结果才能开始加载。几次等待叠加,用户就会觉得怎么点什么都慢。
因此,“下载能跑满”只能说明这项传输利用了较多可用容量,不能独立证明其他任务的响应也好。
排查时可以把两个问题分开:这段时间一共传了多少数据?我刚刚发起的操作,多久才有可用结果?
数据究竟在哪里排队?
一份数据到达目的地,沿途可能经过手机、无线接入点、路由器和运营商设备。某一处收到数据的速度,暂时超过它能往外发送的速度,就需要先把一部分存起来。
队列并不奇怪。网络流量有突发,发送和接收也不总是匀速,适当缓冲有助于应对短时间的不匹配。麻烦的是持续积压:旧数据还没发完,新数据不断加入,后来者的等待越来越长。RFC 7567:网络队列与延迟
用一个简化例子感受一下量级:假设单一先进先出队列前面已有 1 MB 数据,出口速度稳定为 10 Mbps,忽略协议开销,仅把这部分数据送走就大约需要 0.8 秒。这是算术示例,不是某台路由器的实测结果。
新来的请求即使很小,在这个模型里也得先等前面的数据通过。
实际设备可能分多个队列、采用不同调度方式,无线容量也会波动。不能照着这个例子给任何网络直接算延迟,但它能说明:等待多久,既与前面堆了多少有关,也与出口处理得多快有关。
缓冲区更大,为什么没有变得更顺?
一种直觉是:装不下就扩容,能存更多数据,总比丢掉好。
如果只是短时突发,这个思路有用。但出口能力没有增加、数据又持续涌入时,更大的空间可能只是允许队伍排得更长。数据还在,没有立刻丢失,交互却迟迟得不到回应。
这种与过度缓冲相关的高延迟问题,通常被称为缓冲膨胀,也就是 bufferbloat。
它不等于“只要队列大就一定出问题”,更不意味着应该把缓冲全部去掉。真正要避免的是长期维持一条不必要的长队,同时又保留吸收合理突发的能力。
这里的缓冲,也不同于播放器提前存几秒视频。播放器是在为后续播放备货;网络队列里的数据,往往还没到那个正在等它的应用手里。
为什么上传照片,也会让网页变慢?
上传和下载在测速页面里是两个数字,容易让人以为它们完全互不影响。
但一次浏览,并不是只有服务器往手机发数据。手机要先发请求,接收过程中还可能持续发送传输确认。以上下行容量分别受限的连接为例,如果照片上传让上行出口长期积压,这些小数据也可能被拖住。
请求晚发出去,响应自然晚开始;确认反馈被拖慢,也可能影响发送方后续的传输节奏。具体影响取决于协议和调度,不能说只要上行跑满,下载一定降到某个比例。
Wi-Fi 环境中,不同设备还可能争用无线传输时间。于是,你的手机没有运行下载任务,也可能受到同一网络里另一台设备的影响。
反过来,只看到“暂停上传以后快了”,仍不能直接认定就是缓冲膨胀。设备处理能力、无线竞争和其他瓶颈也值得检查。这个操作提供了线索,还没有完成归因。
能不能给着急的小请求留点空间?
应用能先管好自己的任务。比如,用户正在进行交互时,后台备份不必始终追求最高速度;大量可延后的传输,也不必同时启动。
适度限制后台传输速率,有时能减少瓶颈处的积压。但没有一条通用的“限到带宽多少百分比”规则:实际容量会变,其他设备也在用网。限得太低,还会无谓延长任务时间。减少并发同样只是一个可验证的办法,一条大流也可能占满出口。
网络设备则可以通过流量调度,减少一条大流对其他流的挤压,并通过主动队列管理控制持续排队。FQ-CoDel 就结合了这两类思路,目标包括改善交互流量在负载下的体验。
这不意味着打开一个名字叫“加速”或“优先级”的开关就一定有效。措施是否作用在实际瓶颈上、设备能否处理当前速率,都需要验证。应用里的优先级,也不保证沿途网络会照着执行。
测试时,别只给应用一条空闲网络
可以固定设备、测试服务和操作流程,安排几组简单对照:
| 网络负载 | 同时执行的操作 | 主要观察 |
|---|---|---|
| 没有额外大流量 | 打开固定页面或发起固定小请求 | 记录空闲时的基线 |
| 持续下载 | 重复相同操作 | 下载吞吐与交互耗时是否同时恶化或分化 |
| 持续上传 | 重复相同操作 | 上行负载是否影响响应 |
| 停止大流量后 | 继续观察相同操作 | 延迟多久回落,是否仍有积压影响 |
背景流量必须与被测操作共享你想研究的瓶颈。两个任务虽然同时运行,却走不同网络,或者被分别限速而没有共享队列,就不能当成同一种实验。
也可以把大任务放在另一台设备上,减少同一台设备的 CPU、磁盘竞争对判断的干扰。这个对照仍不能排除所有因素,但比只看一台电脑上的卡顿更容易缩小范围。
除了平均值,保留几次特别慢的操作,以及负载开始、停止的时间。一个孤立的延迟数字,看不出等待是否随着流量增加而增长。
固定增加延迟,测不到全部排队行为
给每个包增加固定等待,可以检查应用在高延迟下是否正常。但真实排队会随流量变化:空闲时短,忙起来变长,负载停止后逐渐排空。
如果要研究这种过程,就需要能形成共享瓶颈和相应队列行为的受控环境。只设置一个固定延迟,并不能说明已经复现了家庭路由器满载时的情况。
最终结果也应同时保留两面:大文件完成速度变了多少,其他操作的等待又变了多少。把下载几乎停掉以后,网页当然可能更顺,但这还不够说明方案合适。
下次遇到一开下载就卡,可以先看负载开始前后,同一个小请求的等待有没有明显变化。下载速度很高的那几分钟里,其他数据可能正在出口前排队。 (文章含AI辅助内容)