延迟是消息(message)或分组(packet)从起点到终点经历的时间。这个定义简单明了,但却掩盖了很多有用的信息。事实上,任何系统都有很多因素可能影响传送消息的时间。因此,弄清楚这些因素是什么,以及它们如何影响性能是最重要的。 下面看看路由器这个负责在客户端和服务器之间转发消息的设备,会牵涉哪些影响延迟的因素。 传播延迟 消息从发送端到接收端需要的时间,是信号传播距离和速度的函数 传输延迟 把消息中的所有比特转移到链路中需要的时间,是消息长度和链路速率的函数 处理延迟 处理分组首部、检查位错误及确定分组目标所需的时间 排队延迟 到来的分组排队等待处理的时间 以上延迟的时间总和,就是客户端到服务器的总延迟时间。传播时间取决于距离和信号通过的媒介,另外传播速度通常不超过光速。而传输延迟由传输链路的速率决定,与客户端到服务器的距离无关。举个例子,假设有一个10 MB 的文件,分别通过两个链路传输,一个1 Mbit/s,另一个100 Mbit/s。在1 Mbit/s 的链路上,需要花10 s,而在100 Mbit/s 的链路上,只需0.1 s。 接着,分组到达路由器。路由器必须检测分组的首部,以确定出站路由,并且还可能对数据进行检查,这些都要花时间。由于这些检查通常由硬件完成,因此相应的延迟一般非常短,但再短也还是存在。最后,如果分组到达的速度超过了路由器的处理能力,那么分组就要在入站缓冲区排队。数据在缓冲区排队等待的时间,当然就是排队延迟。 每个分组在通过网络时都会遇到这样或那样的延迟。发送端与接收端的距离越远,传播时间就越长。一路上经过的路由器越多,每个分组的处理和传输延迟就越多。最后,网络流量越拥挤,分组在入站缓冲区中被延迟的可能性就越大。 本地路由器的缓冲区爆满 缓冲区爆满(Bufferbloat)是Jim Gettys 在2010 年发明的一个术语,是排队延迟影响网络整体性能的一个形象的说法。 造成这个问题的原因主要是如今市面上的路由器都会配备很大的入站缓冲区,以便“不惜一切代价”避免丢包(分组)。可是,这种做法破坏了TCP 的拥塞预防机制(congestion avoidance,下一章将介绍),导致网络中产生较长且可变的延迟时间。为解决这个问题,有人提出了新的CoDel 主动队列管理算法,且已经在Linux 内核3.5 以上版本中实现。如果想了解更多内容,可以参考ACM 的一篇论文,搜索“Controlling Queue Delay”就能找到。