为什么有时候下载东西一开始很快,后来就越来越慢?

好吧,纸糊惯例:高票答案纯属一本正经的胡扯八道。

这个是FileZilla,server用来建立ftp服务器,client就不用说了,码农们最喜欢的ftp客户端软件,不知道有没有之一,反正天天见。

The free FTP solution

两者刚好一套。自己配个环境,试试看会不会出现“最后一段下载速度缓慢”问题。

Wireshark,协议分析利器。实际看看TCP协议运作过程。

Wireshark · Go Deep.

不要看见贴几张图片就以为那是标准答案。能几乎每个关键点都说错,学成这样还真是难能可贵了。

1、“慢起动”速度真的慢,但持续时间极短。

慢起动阶段,TCP window从极小(如1、2……10字节等)开始,每个RTT周期下载速度最高增加一倍(RTT已知时,TCP window大小和传输速率成正比,故可认为每个RTT周期下载速度增加一倍)。

出现第一个丢包或满足其它条件时(其它条件较复杂,不讨论),慢起动停止。

对常见的宽带链路,哪怕RTT取50ms,那也是每50ms链路下载速率翻一番。1秒钟足够下载速率上涨2^20倍。

哪怕最不利情况下,几秒钟也足够跑到链路带宽上限了……

神TM的“初始下载速度快是因为慢开始”。

2、“拥塞控制”很稳。

如前所述,你先下个FileZilla-server搭建个环境,然后用FileZilla-client从上面下一个大文件(比如高清视频/游戏安装包什么的)。

打开任务管理器,性能-以太网,看看下载速率稳不稳,是不是一本道答案那样大起大落。

恰恰相反,几乎所有的拥塞控制算法都可以保证“实际数据传输速率在网络允许的最大带宽附近波动”——实际到任务管理器里面看看是不是这样。

神TM的“后面一直减半减半减半就会越来越慢越慢越慢”——真要把程序写成那样,搞网络的还是买块豆腐碰死算了。

3、“快速重传”对拥塞控制算法的影响很复杂,不同算法有不同的应对。

TCP congestion control

要谈论“快速重传”,需要先搞明白DUP ACK。

DUP ACK是这样一种机制:通常情况下,接收端收到发送端发来的包后,需要回一个ACK包。这个ACK包的作用是“通知发送端,编号xx的包我已经收到了,请继续发编号xx+1的包”。那么如果包10延误或丢失了,接收端就可能在收到包9后收到包11、12、13……协议规定,当收到这样不按顺序到来的包时,接收端也要回一个ACK,但这个ACK不能确认包11收到(因为TCP协议允许用一个ACK确认一系列包,比如对包11的ACK意味着包11之前的所有包已经全部收到),而是重复报告“包9已收到,请求包10”——这就叫DUP ACK。发送方见到这种DUP ACK,就明白接收方收到的包乱序了。

正常情况下,一个包必须经过足够长时间才能确认其丢失,然后发送端才会重传它。这个响应周期太长了,对传输速率影响太大。于是有些算法就利用DUP ACK:一旦连续出现3个DUP ACK,就认为报文已经丢失,于是立即重传DUP ACK请求的下一个包。这就叫“快速重传”。

快速重传大大加快了网络拥塞的发现/响应速度,依赖它的算法自然就会比“超时重传算法”更“精细”一些——换句话说,就是“在网络允许最大带宽”附近的波动更“细碎”一些,对网络带宽的利用率也更高。

重复一遍:拥塞控制算法的目标是尽量提高网络带宽的利用率、同时尽量保证每个链路公平分享带宽。所谓“拥塞控制算法导致下载越来越慢”纯属胡扯八道。

PS:google最新的BBR算法无视DUP ACK。它比旧有算法更接近本质。

但这些和主题无关,故不再深入讨论。

TCP BBR算法与Reno/CUBIC的对比

————————————————————————————

如果大家亲自搭建ftp服务器做过实验,就会发现,哪怕下一个100G的大文件,整个下载过程都是非常平稳的:除了最开始速率略慢、但1秒不到就到了网速上限然后一直保持,直到文件全部下载完毕,没有任何波动。

但是……网上到别人的服务器下载文件可不是这样啊?

无论如何,我们已经通过实验证明了,TCP/ftp协议本身没有问题。那么我们就不需要继续在上面浪费时间了。

那么,问题在哪呢?

1、很多朋友谈到“多线程下载”了。尤其对P2P下载,这的确是一个重要影响因素。

这是因为,前面提到过,TCP拥塞算法要保证“每个链路公平分享带宽”——嗯,如果一共10M带宽,我和张三等十人每人一条链接ftp下载,那么每人都能达到1M的下载速率,很公平,对吧?

但,如果张三耍流氓,他多开了一条链接呢?

现在成了每条链接0.9M带宽,仍然很公平,对吧?

……当然不对!

张三是两条链接,他有1.8M的下载速率;而其它9人每人只有1条链接,所以只有0.9M的带宽。

怎么办?多开链接呗。你敢开三条,我就开四条……你开200条,我开400条……谁开的多谁抢到的带宽就越多,傻子才不开。

(网管:现在你们明白为啥要禁P2P了吧)

(服务提供商也不干了:每条链接都得有个接受/发送缓冲区,这可都是内存啊。你们这么整,我服务器还不得累死。不行,我得配置个策略,每个用户/ip至多只准建立一条链接[实际一般为1~5条],多了就强制断开,反复重试我ban你ip)

(举例只是类似宿舍共用路由的情形;实际上网络任何部分都可能出现瓶颈。但一般来说,瓶颈多出现在末端,即用户路由器和内容提供商服务器那里;另外就是跨国通信带宽不足导致瓶颈——电信-联通这种奇葩情况不予讨论)

下载一个文件时,只剩最后一点点了,多开链接就不划算了——还没跑满带宽就搬回来了,开越多反而更慢,还讨人厌;还有的干脆从协议上就不支持过小的分块……所以多线程下载到最后,只能1条链接搬,速度自然就慢了。

但,如果仅仅是争抢带宽的话……经常P2P下载单链接也能跑到400K啊;为什么只剩一点点时,速度总是只剩2~3K?

这是因为:

2、资源提供者的心机

我们知道,P2P号称“下载者越多速度越快”;原理很简单,程序会自动让每个人把自己下载到的部分分享出去,下载的人越多,分享者自然也越多,速度当然就越快了。

但现实中,有些人只下载不上传(这种行为被形象的称为“吸血”);同时,多数用户的下载带宽和上传带宽不对等(说的就是你,ADSL;其实现在的光纤宽带,一般也多是下载带宽几倍于上传带宽);最后,多数人夜里挂P2P软件,并且会设置“下载结束后关机”。

这就导致下载量总是远大于上传量——这么一来,“人越多反而越快”就成了一句空话,玩不起来了。

怎么办?

检查谁快下载完了,限他的速,让他多做会儿种。

类似的,普通的下载站,他们当然希望吸引更多用户;怎么吸引呢?丰富的内容+更高的下载速度。

但,想提供更高的下载速度,就必须购买更多的带宽……可买带宽是需要钱钱的……

怎么办?

当同时下载量太大时,发现一个用户刚开始下载,就给他一个更高的限速,允许他“光速下载”;下载一段时间后再限速——用户没耐心一直盯着看,刚开始速度快让他很高兴,中后期他不看了就降速节约带宽:这就解决了“更快的下载速度”和“带宽得花钱买”之间的矛盾。

于是,买下和竞争对手一样多的带宽,用户就是感觉我更快!

————————————————————

最后,很多人可能会奇怪:下载到最后一点点,速度总是很慢;我暂停/断开一小会儿,重新开始时下载速度就会很快,然后很快又降低到原来的程度了,这是为什么?

不,这可不是因为高票那个一本道答案的“慢起动”。

要说清这个,咱得从限速算法的原理说起。

具体细节太复杂了;简而言之,为了满足各种刁钻古怪的要求,限速算法的原理并不是直接限制网络传输速度(没法实现),而是“你想传出去每一个字节的数据,都得得到我的授权;而‘授权令’的产生速度很容易控制;那么如果我每秒只产生1M个授权令,你的传输速率自然最高只有1M/s;最后,规定‘授权令’可累积,但有上限”。

“授权令“用术语说就叫”桶“。如果每个桶容量是1K字节,那么我每秒产生10个桶,你的传输速率就只有10K;我每秒产生1000个桶,你的传输速率就是1M;但我还可以规定每个用户最多只能积攒500个桶,多了不用,我就认为你没数据要传,更多的授权自然过期作废。

明白了这个,问题就很容易解答了:下载到最后速度很慢是因为限速,给你的桶产生太慢,产生一个你用一个,传输速率自然就被限到几K了;暂停/断开后,桶就给你累计下来,那么恢复传输后,你就可以一次性把积攒下来的桶给用完——于是瞬时传输速度就飙到了几百K甚至若干M;一旦桶用完了,传输速率自然又回到了几K……

你以为自己得了实惠……实际上,瞬时几百K的速度用的还是暂停时本就该分给你的桶;反倒是,因为暂停/断开时间过长,你还因为溢出而浪费了很多桶……

PS:很多软件计算传输速率用的是平均值。所以看起来传输速率并不是暴起暴落,而是先600K后300K然后160K最后又回到20K;但实际上只有第一秒是600K,第二秒已经是20K了;但它把两秒的流量加起来一平均……

PS2:有些时候,因为最后一段时间被严重限速,导致相关线程优先级过低;然后如果软件实现有问题,就很容易在这段时间暴露出来。此时断开链接重试就类似网络版的“重启下说不定就好了”。对这种情况,断开重试的确有助于提高最后一段的下载速度。

PS3:国内因为墙的干扰,有时下载正常内容也会遭遇墙发来的RST包。这也会导致下载中断。由于大多软件不知道如何处理RST包(这种报文太特殊,正常情况下压根就不应该出现),故此时往往只能通过人工干预恢复……

PS4:如果你对网络感兴趣,想知道更多……那么装个Linux吧。装虚拟机里面也行。

Linux实现了几乎所有的流控算法,你可以从中自由选择,以便观察它们在实际网络环境中的表现。

你可以很容易的使用TCP DUMP配合脚本,深入观察/分析各种算法的表现;还可以利用TC模拟网络抖动、丢包、乱序等几乎所有你能想到的奇葩状况,从而观察异常情况下各种流控算法的实际表现。

来源:爱听音乐的游戏王者

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2017年6月9日
下一篇 2017年6月9日

相关推荐