通过TCP应用在访问国际出口的时候通常都会很慢、很卡,例如用浏览器上网、播放视频,或者某些我们称之为科学上网的行为。
卡顿的体验主要源自于几下几点原因:......
一 高延时,现在电信ping到美国往返延时在170ms,已经很不错了,之前都是200ms到300ms。高延时会造成一些应用交互体验不佳,比如打开一个网页:一次tcp协议握手,一次页面请求,再根据页面元素继续请求剩余资源,至少3个往返来回。
二 高丢包率,闲时丢包3%左右,忙时丢包10%以上,尤其是晚间。这个丢包主要是下行线路丢包,做过一次测试,发一千个ping数据包到海外服务器,对方tcpdump收到完整的1000个请求报文并作为回应,而本地丢包率10%。
这么高的下行丢包率是什么造成的呢?一来国际出口带宽有限,大量数据都从这个狭窄的瓶颈蜂拥而来就造成了拥塞,路由节点处理繁忙必然会丢包。二来推测,国内高墙会策略性丢包,比如普通用户优先级比较低还是什么别的策略。
三 连接重置,就是强制TCP reset,经常发生在一条tcp连接正在交换数据的时候,冷不丁冒出来一个tcp reset报文掐断你的连接。这种行为前几年大家应该都见到过,尤其是在搜索引擎中搜索敏感词的时候。现在这一招依然存在,比如检测到你使用某些不符合法规的软件或者流量异常的时候。
这里面最主要的问题还是丢包,因为丢包对于tcp速率的影响是致命的,为什么你网页加载要很久,播放视频要缓冲半天,下载也只有几十k呢?下面简单科普下tcp协议的拥塞控制设计。
一.TCP的拥塞控制
TCP流在刚建立连接准备下发数据的时候,它不是一下子就大量发包的,如果这样设计的话,网络早就过载了,也造成不必要的带宽浪费。它会慢慢试探网络状况,称之为慢启动阶段,一开始发送一个报文段,收到对方的ack响应后,再发送两个报文段,然后逐渐增大发包量,直到增大到慢启动门限。所以tcp下载时流量是逐渐达到峰值的,此时tcp发送者维护的发送窗口大小叫做拥塞窗口。
慢启动阶段过后,假设此时突然发生丢包,tcp设计者认为此时网络出现了拥塞,需要调整发送流量,于是马上把tcp拥塞窗口大小减半,必要时甚至再次进行慢启动。
由此可见,TCP拥塞控制窗口的原则是AIMD原则 —— Additive Increase Multiplicative Decrease,即加法增大,倍数减少。该原则可以较好地保证流之间的公平性,因为一旦出现丢包,那么立即减半退避,反复的震荡和收敛,可以给其他的流留有足够的空间,从而保证整体带宽占用的公平性。
TCP的这种设计是一种良性设计,如果人人都遵循这种设计,世界无疑是公平的美好的。然而实际上好人遇上坏人总会要吃大亏。总有人利用好人,也总有人破坏公平。下面聊下我对tcp加速的一点浅见。
二.单线程TCP加速
列出几个典型的:
1.net-speeder,该程序单向加速安装简单,有不少用户群。但原理其实非常简单粗暴,用双倍甚至四倍的发包量来抵抗丢包,效果良好,流量巨大,手段下流。大量的同类软件停留在这个层面。
2.速锐,商业软件,hack进内核,替换了tcp算法,效果是最突出的,据说只用了20%左右的额外流量换取了十几倍的下行速率。
3.自己实现可靠传输和拥塞算法,例如kcp协议,实现了类tcp的可靠传输机制和专为加速设计的拥塞算法,对上支持流模式和保留数据边界的报文模式。kcp仅实现核心协议算法,对上对下都有接口,源代码为C语言,精巧高效。程序已经在github上开源,已经被很多人用来在udp协议之上层实现加速隧道。据作者介绍,仅以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度,还是很不错的,相对也很公平。
私有算法通过udp隧道进行数据加速是个比较好的办法,udp隧道其实网上有各种开源实现,加密后可以做成单通道的转发隧道,也可以利用tun虚拟成网络设备。udp可以天然对抗tcp reset,但在网际网路上转发的时候可能会被节点视为低优先级数据,因为udp协议过于简单本身就被视为不可靠协议,再加上也不提供拥塞控制,对带宽的占用是贪婪无节制的。还有如果同一端口长时间数据量过大也容易被检测和遭到封堵。
单条隧道的实现不难,但能在隧道中复用多路socket数据的实现很少见,目前据我所知只有ssh能仅在一条流中复用各种socket应用:shell、端口转发、文件传输等。但这背后需要复杂精密的管道处理工程。
在推动网络协议优化上面,IT巨擘谷歌公司也一直在持续研究跟进,其推出的基于udp协议的改良协议QUIC已经嵌入到了chrome浏览器中了。
也还是谷歌,对tcp协议也贡献了自己研发的BBR拥塞控制算法,该算法已经被近期发布的最新linux 4.9内核所包含了,据说该算法对改善丢包和保持流速效果非常明显,值得期待。
三.多线程TCP加速
HTTP1.1协议定义了range字段,可以指定数据的起止字节偏移。原来下载一个文件需要从头传输,现在可以任意从指定位置传输数据。多线程下载工具就是这个原理,将一份文件切割成多份,多线程一起下载,一个tcp流丢包,那多个线程多条流加起来速率总可以了吧。
多线程加速方式适用于文件下载、流媒体播放,需要对协议、算法、资源进行稍微整合即可实现。
四.总结
程序员群体真的是智计无穷,又很有韧劲,什么问题都能找到解决的办法,又很无私,开源程序不计其数。其实很多东西都可以商业化,只是很多人单枪匹马,做出东西只能选择开源和通过捐助的方式获利,但当今社会,只有很少很少人会尊重智慧劳动,并且还自愿付出酬劳。
最后,本文仅用于科学研究.
No comments:
Post a Comment