路由器缓冲区膨胀导致的TCP传输延迟
今天在看《TCP/IP详解》的时候看到一个缓冲区膨胀的问题,大致的意思是,网络中的路由设备,其缓冲区的大小不是越大越好,过大的缓冲区反而会导致网络拥塞。
对此表示不解,于是简单进行了搜索,发现这个问题还是很有趣的,所以拿出来讲一下。先说结论,网络设备的缓冲区并不是越大越好,也不是越小越好,而是需要根据链路速率和RTT进行计算,得到一个经验值。
缓冲区过小
缓冲区过小的问题很明显,如果缓冲区太小,很容易就被写满了,只要不能进行适当的排队,丢包率会高,导致传输效率差。
缓冲区过大
缓冲区过大的时候事情就变得有趣了,理论来说,缓冲区大了,丢包率下降,传输质量应该上升啊?但是实际上不是的,我们需要考虑以下问题:
1,丢包率下降到一定程度之后,丢包率下降带来的传输质量提升非常有限
2,设备的接收速率不一定等于设备的发送速率,当接受速率远大于发送速率时,缓冲区增加并不能加快发送速率
3,TCP这种带超时重传的协议,如果不能再重传的时间内收到ack,路由设备的缓冲和丢包就没有区别了。
带着这三个问题,我们看一下以下场景
上图中,我们假设中间的路由设备的buffer极大,理论来说无论来多少数据,都能buffer起来。
中间的路由设备,接收速率是1M/s,而发送速率只有10k/s,下面的蓝色箭头表示发送方发送的数据,紫色的箭头表示接收方返回的ack。
在这个假设下,以下事情会依次发生:
1,路由设备不停缓冲数据,接收端以10kb/s的速度接收数据,并且返回 正确的ack
2,发送方以比较缓慢的速度,逐渐收到 正确的ack
3,发送方认为当前发送速率能正常发送,于是加大拥塞窗口,往链路注入更多的数据
4,重复1~3,直到发送方发现某个数据包在RTT内没有ack,进行重传,理论来说,从该seq之后,到重传开始前发送的数据,都需要重传,因为中间路由buffer足够大,超时不是真实丢包产生的,所以不存在前面的包没发送,而后续某个包被发送的情况,所有包都在队列里。
5,由于中间路由仍然buffer住了之前发送过来的数据,重传的数据将会append到buffer中,这时buffer开始出现冗余数据。
6,尽管中间路由的buffer出现了冗余数据,但是路由器是不在乎tcp层数据的重复性的,他只管转发,所以,他会把之前的数据,和重传的数据都发送出去,导致重传的数据也很有可能超时,tcp发送端进一步重传数据,重复4~6的步骤。当然,由于超时重传会缩减拥塞窗口,重传会变少。
可以看到,在中间路由的buffer很大的情况下,中间链路被注入了大量无效的数据,降低了传输的效率。
那么在buffer正常的情况下,我们期待的行为是什么样呢?
如果buffer合适,他会出现这样的行为:
1,路由缓冲部分数据,以10kb/s发送,过多的数据会被丢弃
2,由于路由仍在发送,buffer总会有空闲,会出现abc三个包,b包丢弃,但是c包被正确缓冲,发送的情况。
3,接收端接收到跳序数据包,返回 重复的ack
4,接收端收到重复ack,发现链路丢包,主动降低发送速率
此时,链路的传输效率反而得到了保障。
但是,并不是所有的tcp版本都有缓冲区膨胀的问题。
相关参考: