背景介绍
最近在实验过程中发现RTT增大后CUBIC的吞吐会随之下降,因此想通过实验查找原因。
通过查阅资料得知:影响网络吞吐的因素主要存在于三个地方:
- 发送方(拥塞控制)
- 网络环境(丢包、延迟增大)
- 接收方(流量控制)
实验中,我们假设网络环境不存在丢包,只考虑RTT对吞吐的影响。因此原因可以定位在发送方和接收方。
实验设置
实验在基于容器的实验环境下开展。
- 使用Linux tc控制Sender网络接口的delay,从而控制RTT;并且使用wireshark在Sender进行抓包。
- 网络带宽设置为200 Mbps,丢包率为0%
- 实验中Sender的发送缓存保持不变,通过改变Receiver的接收缓存观察实验结果的变化。
发送缓存和接收缓存的具体设置可分为2组:
序号 | 发送缓存 | 接收缓存 |
1 | 4 MB | 6 MB |
2 | 4 MB | 20 MB |
ps:发送窗口最大值和接收窗口最大值分别受发送缓存和接收缓存影响,所以可以通过更改发送缓存/接收缓存来更改发送窗口最大值/接收窗口最大值
实验结果分析
在实验过程中使用tcpdump进行抓包,使用wireshark对抓包结果进行分析。
接收缓存:6 MB
wireshark --> Statistics --> TCP Stream Graphs --> Window Scaling
首先对结果图进行说明:
- 蓝色曲线:Sender已经发送但是还没有被确认的数据量(flight)
- 绿色曲线:Receiver通告的接收窗口的大小
上图实验过程中我们将RTT设置为200 ms,此时吞吐约为120 Mbps,链路利用率约为 (120/200)*100%=60%
从图中可以看到接收窗口保持在4 MB左右,flight基本保持和接收窗口大小一致。因为CUBIC使用min{cwnd, rwnd}作为发送窗口的大小,由此我们可以初步判断是接收窗口限制了发送速率,下面我们具体分析:
wireshark --> Statistics --> TCP Stream Graphs --> Time Sequence(tcptrace)
首先对结果图进行说明:
- 棕色曲线:Sender收到确认的序列号(每次棕色曲线上升代表此时Sender收到了ACK)
- 绿色曲线:接收窗口可容纳的序列号(Sender收到的ACK中带有Receiver通告的接收窗口大小)
- 蓝色短横线:Sender发送数据的序列号
从图中我们可以看到,每两次棕色曲线上升的间隔(即每两次收到ACK的间隔)大约是200 ms,也就是RTT的大小。
每次棕色曲线的上升都会伴随着绿色曲线的上升,这里可以理解为:ACK携带的接收窗口信息告诉Sender接收方此时可以接收更多的数据。
图中蓝色短横线随着绿色曲线上升而上升并且上升的蓝色短横线和上升的绿色曲线重合,这里可以理解为:Sender收到ACK后释放了发送窗口中的空间,此时可以发送数据,发送的数据量取决于接收窗口的大小。
到此,可以初步解释当接收缓存较小时RTT对CUBIC的影响:CUBIC发送数据的时候会将发送窗口中的数据突发出去,为了保证可靠传输,需要等待已发送数据被确认后才能再次发送数据。图中可以看到每两次突发数据(蓝色短横线上升)的间隔为200 ms,也就是RTT的大小。因此当RTT较大时,等待ACK的时间也越长,每两次突发数据的间隔也就越长,最终导致吞吐下降。
为了优化较大RTT中CUBIC的吞吐,我们可以增大Receiver的接收缓存,使rwnd不再是一个限制吞吐的因素。下面介绍将接收缓存设置为20 MB后的结果。
接收缓存:20 MB
wireshark --> Statistics --> TCP Stream Graphs --> Window Scaling
上图实验中RTT仍然设置为200 ms,此时吞吐约为160 Mbps,链路利用率约为 (160/200)*100%=80%
从图中可以看到接收窗口大小约为10 MB,明显大于flight数据量(约为4 MB),现在可以初步判断接收窗口已经不再是限制CUBIC吞吐的因素。
wireshark --> Statistics --> TCP Stream Graphs --> Time Sequence(tcptrace)
从图中可以看到接收窗口的序列号均大于发送数据的序列号,此时可以排除接收窗口对吞吐的影响。那此时限制CUBIC吞吐的因素又是什么呢?答案是:拥塞窗口(cwnd)。
我们知道,TCP使用拥塞控制和流量控制,在保证可靠传输的同时避免网络发生拥塞。而发送窗口的大小取决于cwnd和rwnd中的较小值。当rwnd大于cwnd时,发送窗口的大小实际上就是cwnd。当每次将cwnd中的数据全部发送出去之后,Sender会停止发送等待ACK。ACK会告诉Sender哪些数据已经被Receiver接收,然后Sender会释放这些已经成功传输的数据在cwnd中占用的空间,此时Sender才可以继续发送数据。而当RTT较大时,等待ACK的时间也会变长,因此吞吐会受到影响。
增大发送缓存也会缓解这种影响,但是可能会导致网络拥塞,因此不推荐这样做。
实验结果对比
对于每组缓存配置,我们分别观察RTT取 [100ms, 150ms, 200ms, 250ms, 300ms] 时CUBIC的吞吐。
可以看到CUBIC吞吐会随着RTT增大而下降,接收缓存为20 MB的吞吐要明显高于接收缓存为6 MB的吞吐(大约高30%)。
总结
由于CUBIC发送数据后会等待确认,然后再发送数据,因此当RTT较大时等待时间也较长,最终导致吞吐受到影响。当接收缓存较小时,可以通过增大接收缓存来优化吞吐(一般将接收缓存设置为与BDP相等或稍大一点)。