IM即时通讯开发如何提升移动网络下图片传输速度和成功率
作者:互联网
在本案例中,我们重点讲解了提升上传速度和成功率的“鱼翅”项目,重点分析了在移动网络下影响上传速度和成功率的因素,一次次的调优算法并验证,最终提炼出了能应对网络质量瞬息万变的鱼翅算法。
“大白鲨”的第一个阶段,我们详细分析了当时 MIG 几大产品的上传方案,了解到每个方案中都有一些可取之处、也存在一些都没解决好的问题,于是我们决定把这些各自的“闪光点”都放到“鱼翅”中作为一个基础。同时,我们针对大家都没处理好的一些问题提出我们的一些改进设想,于是,我们有了鱼翅的方案雏形。
➨由于不便展示具体流程图,故仅将其要点和相关考虑罗列如下:
(1)必须分小片传输一个文件(图片):
理由:由于当时后台的能力,无法支持单个网络包传输失败后对包里剩余字节的断点续传,所以若整个文件(图片)放在一个网络包里进行传输,一旦失败,就必须重传整个文件,这样给用户带来的流量浪费是巨大的。因而采用把一个文件分片的方式传输,则只需要在某一个分片失败后重传这一个分片。同时,单个消息越大传输时越容易失败(快速数学证明:若文件大小接近 0,则传输成功概率接近 100% ;而文件大小无穷大,则传输过程必然会失败),而移动互联网的整体质量比有线网络要差,相同大小的消息会更容易失败;因此就应该把一个较大的文件分成一个一个的小片进行传输,每个小片更容易成功一些。
(2)不同类型的移动互联网下的分片初始大小应该有所不同:
理由:不同移动互联网的带宽和稳定性的差异都很大,如 WiFi 和 2G,使用不同大小的初始分片应该能更好的适应对应类型的网络,但是至于每种网络下的初始分片到底多大,这需要进行实验。
(3)在上传一个文件(图片)的过程中,应当尽可能动态增大分片大小(例如,后一片是前一片的 N 倍),以减少分片数量:
理由:分片动作会带来不少额外开销,如 C / S 两端拆分与合并分片的时间、传输时的额外流量( HTTP 头等)、每个分片的 RTT 等等诸多开销,所以理论上传输同一个文件用的分片数量越少,应该额外开销越小。
(4)确定每个分片是否要继续增大之前,要检查网络类型是否发生了变化,一旦跟前一片传输的网络变得不同,则新的一片不能继续增大而是转而用新网络类型下的初始分片大小进行传输:
理由:移动互联网下,由于用户的“移动”而时长发生网络类型切换的事情(如, 3G 变 2.5G),一旦网络类型变了,其带宽、时延、稳定性等等因素都发生了很大的变化,所以需要分片大小需要“归零”,以迅速适应新的网络,减少失败的概率。
(5)分片一旦传输失败,应当使用该网络下的初始分片大小进行重试:
理由:若网络类型并没有产生切换,但某分片传输失败了,则说明该网络的质量可能已经下降到不再适合传输这个大小的分片,会有较高再次失败的可能性,因此转而重新用该网络下的初始大小的分片进行重试,以提升重传成功概率、同时减少再次失败所带来的流量浪费。
(6)每个分片都有一定次数的失败重传机会,当一个分片的所有重传都失败了,才定义为图片传输失败。
(7)配合后台服务器能力,待用户手工再次重试失败传输的图片时,能断点续传。
待解开的疑问
➨鱼翅的这个方案雏形尝试改进了当时各业务上传图片时存在的不少弱点,举几个例子。例如:
有的业务不把图片进行分片传输会导致的失败率高、流量浪费多;
又例如有的业务尽管用分片传输策略,但分片的大小时是固定的,这样一来,优质网络下的带宽利用率可能就很低(传输速度远不如不分片传输的那种方案);
还有的方案是重传失败分片时并不改变其大小,因而重传的成功率并不高。
➨尽管新方案有了不少改进点,但我们心中仍然存在不少疑问,若能找到答案,则鱼翅就会更加可靠和强大,这些疑问如下:
疑问 1:关于“长连接”:
由于图片传输时,使用的是 HTTP,那么是否当时的所有运营商网络都支持 HTTP 的 Keep-alive 这样的长连接?如果不支持,那么会导致每一个包含分片的 HTTP 请求都要进行一次 TCP 的 connection,依据我们的经验,移动互联网下的连接成本很高, 2G 网络下甚至有时高达 2S。如此大的分片开销是完全没法接受的!所以,如果运营商网络都支持 Keep-alive,则一个文件(图片)的多个分片传输仅需首个分片传输前建立一次 connection ;甚至,多个连续发送的图片都可以复用第一张图片建立好的连接。
疑问 2:关于分片大小:
如果在传输过程中,后一片分片总是 N 倍于前一片分片的大小,那么,不同类型、不同质量的网络下是否存在最适合的初始分片大小和最大分片大小?如果没有最大分片,岂不是越到后来传输失败的概率越大?
疑问 3:关于分片对于速度的影响:
显而易见,如果将原本不分片的传输方案改造成分片传输,由于分片引入的开销,必然导致传输速度会有下降;那么,有没有办法让这一下降的幅度尽可能的小,从而在不影响用户速度体验的前提下,通过分片方式得到提升传输成功率和减少流量浪费的好处呢?
疑问 4:关于分片传输成功率:
对于单个分片的传输,其失败的诸多原因中最主要的到底是什么?如果能找到办法解决这个最主要的导致单片失败的问题,岂不能提升单片传输成功率,从而进一步提升整个文件(图片)的上传成功率呢?
疑问 5:关于失败重传策略:
当前的失败重传策略是否奏效,是否是最好的?如果不是,那么还不如不重传,因为如果重传成功率低,必然带来新的浪费。
➨为了解开这五大疑问,我们开始了长达数月的几类自我解惑的工作:
对于“疑问 1”这样的有关运营商的问题,我们找到了熟悉相关行业技术的专家请教,得到初步答案后,开始通过各种网络下的实验进行核实。
对于后面四个疑问,我们先采取在不同特征网络下的大量实验、配合抓包数据分析的手段来定性。
同样对于后面四个疑问,在基本定性之后,我们则采取开发实现鱼翅、然后在不同网络下进行参数的调优实验的方式来定量。
在定性和定量阶段,不断根据更加深入的认知,去优化鱼翅的方案。
➨功夫不负有心人,在成百上千次实验后,上述 5 个疑问的初步答案基本浮出水面:
关于“长连接”的答案:
当时的运营商网络基本都支持 HTTP 的 Keep-alive,通过实验发现,不仅一张图片的分片可以复用第一分片建立的 TCP 连接,有的时候时间间隔稍短的下一张图片甚至也可以复用上一张图片的连接。这样就不必担心分片会带来的巨大网络开销。
关于分片大小的答案:
不同网络下的初试分片大小非常难确定,或者根本就不存在,但最好根据网络的理论带宽各自取一个较小的经验值(后文会给出);分片的大小上限则应该存在,后文讲述的鱼翅核心思想会提到为什么有,且我们怎么去找。
关于分片对于速度的影响的答案:
基于上一个问题的答案,这个问题比较好回答,就是只要有算法能尽可能快的找到“当前网络下的分片上限”,用这个上限值去发送分片,就能将分片带来的速度下降体验减轻到最低。
关于分片传输成功率的答案:
根据我们大量实验的结果,发现移动网络的质量经常会发生的特殊变化(下文会详细讲述这个“特殊”)是传统的网络超时算法不能适应的,而这种不适应,非常容易导致传输超时带来的失败。所以,我们把寻找适合移动互联网的“传输超时算法”作为提升分片传输成功率的关键。
关于失败重传策略的答案:
还是由于移动互联网质量有时发生的特殊变化,所以当时失败重传策略的确有优化空间,下文会讲述如何优化这个点。
随着对几大疑问的不断认知,我们也不断地改进着鱼翅,终于得到了 1.0 版本的鱼翅方案,本章节将会与各位详细聊聊鱼翅正式版的一些核心思想。
相比鱼翅的方案雏形, 1.0 版本的主流程有如下改进:
1)为了能更为快速的寻找适合当前网络的分片大小上限,分片大小的计算逻辑抽象成独立的复杂模块,我们叫它
SSCM,它专门负责根据一个文件的已传输分片的统计数据来计算下一个待发送分片的大小,这样就实现了“自适应动态根据网络现状调整分片大小”的效果;
SSCM 是鱼翅的要点之一,关于 SSCM 的详细情况下一小节会细讲。
2)单一分片在“雏形”中会直接交给 HTTP
协议栈进行传输,而在 1.0
版本中,这个“传输”动作改进成较为复杂的一个独立事务,全新的超时处理方法的秘密就在这里,单片发送成功率的提升就是这样达到目的的,所以“单片发送流程”也是鱼翅的另外一个要点,详情也会在后续小节详述。
3)重试策略也是鱼翅的一个要点,相比方案雏形最大的改进,就在于每一次重试的时间间隔不再是“立刻重试”,而是选择类 TCP 超时重传机制的指数回退方式进行,因为我们做了多次实验发现,移动互联网下做立刻重试是非常不明智的,重试失败率近 100% ;因为,移动互联网网络出现问题后的恢复周期远长于有线网,需要给它更长的时间让其主动恢复,或者手机用户主动运动以改变所处的网络的质量,而运动也需要花较长的时间;因此我们选择不立刻重试,而是等待一段时间(例如, 10S),如果再失败,我们等待更长时间。经多次测试发现,如此的策略能极大提升重试成功率,避免不必要的重试。
接下来,我们展开讲述一下 SSCM 和单片发送流程的主要思路。
SSCM 的核心思想是“鉴古通今”,即每一个分片发送的大小、速度等信息都是后续分片大小计算的依据。因为移动互联网随时在发生着变化,我们处理当前的事务时,一定不能忘记刚刚发生的事情以及历史上发生过的事情,这些数据都是宝贵的财富,我们应当想办法充分使用它们。同时,由于移动互联网带宽资源是有限的,所以尽量不要做为了搞清网络状况而发起一些额外探测包的事,这样只会加重本已负担很重的网络负荷。因此,应要想办法利用必要的数据包发送时所反馈出的一些信息来分析网络状况。
通过对大量的实验数据进行分析和思考,我们认为每一个网络(某个时间、某个地点的某一个类型的移动互联网)都应该有一个最适合的分片传输大小,在这个大小下进行传输,所能达到的速度相对接近某个极大值,对该网络的带宽利用也最为充分。基于上述考虑,我们将 SSCM 的原理画了一张手绘图,下面结合图 5-1 研发过程中的手稿,谈一谈 SSCM 的要点。
1)把一个文件传输的全过程按照分片大小的增长快慢分成三种状态:
QUICKSTART(快启动,分片以一定倍率快速增长)、 SLOWSTART(慢启动,分片以一个远小于快启动增长倍率的小系数缓慢增长)、 STABLE(稳定态,分片大小不在变化)。
解释:状态迁移的触发条件是“分片传输速度随分片大小的增大而变化的幅度”,即图上的“归一化斜率”。结合“手绘图 1”,通过大量实验发现,任意网络的最大可用带宽肯定不同,分片从小变到大,其传输速度也随之增大(增速也不同),但是分片增长到某个大小(我们姑且称这个大小为 Ss,其实这是一个范围)之后再继续增大,对速度不仅不再有正向影响、有的网络下反而会让速度减小。这个实验结果很重要,因此鱼翅在传输图片时最初的状态是 QUICKSTART,目的是以一个较快的增速把分片大小增大到 Ss,而不希望待文件(图片)都传完完毕时,分片的大小仍比 Ss 小很多,这样的上传是没有充分利用网络带宽的。而快启动之后会切入慢启动,即从快启动下的最大分片 Smax 回退到前一个次大小分片 Slmax,然后从 Slmax 为基数、以一个相对较慢的微调增速放大分片,最终找到 Ss,进入稳定态不再改变分片大小,直到发送完毕。
可能有人会问,跨过 Ss,继续增大分片有何不妥?两点理由: 1 是有的网络下速度反而下降,原因是网络负担加重会导致 TCP 重传增多(实验结果); 2 是分片越大,失败概率越高(数学和实验双重证明)。
STABLE 态下如果速度发生巨大变化(我们的经验值是,超过 20% 的变化),我们认为网络质量发生了巨大变化,当前的 Ss 已经不适合了,就会且回到 QUICKSTART 重新寻找新的 Ss ;这里之所以不会试图分析变化趋势而对原有 Ss 进行微调,主要是无法做简单分析来判断到底网络是变好了还是变坏了,读者朋友们有兴趣可以想想。即时通讯聊天软件app开发可以加蔚可云的v:weikeyun24咨询
➨2)不同类型网络下的初始分片大小皆为测试经验值,具体数值是多少借鉴意义不大。原则就是带宽越小的网络初始分片大小越小,带宽相同的情况下, WiFi 下的初始值也大于移动网络的。
解释:尽管 3G 网络的速度很多时候都跟 WiFi 差不多甚至还更快,但是 3G 网络的流量收费,而 WiFi 不收,所以保守一点进行首片试探。
➨3)若待传输图片(文件)小于某个经验中的“较小值”,我们认为是“小”图(文件),传输它时对应网络下的初始分片大小会增倍。
解释:对于小图,总共的分片数量较少,所以通过放大初始分片大小,可以显著减少分片数量,从而提升速度效果明显。
➨4)每一种状态下的分片大小增长因子都不同, QUICKSTART 下是相对最大的值 N,慢启动下是比 1 略大的 M,稳定态下就是 1(不改变大小)。
➨5)每一个新计算出的分片大小都会使用不止 1 次,计算是否切换状态的速度也用的是多次的平滑值,原因是大量测试发现,移动互联网的网络速度抖动比较大,因此希望多次确认出一个稳定的速度,不然很有可能因为某一次速度的突然降低而找到一个远小于真正 Ss 值的稳定态。(在鱼翅的 1.1 版本中这个点有较大的改进,后文会提及)
➨6)判断几个状态是否切换用的是分片大小、平滑速度一起计算出的“归一化斜率”,这个斜率能较为准确的反映上面“手绘图”中的分片大小于对应速度的曲线图。具体用什么斜率来作为切换也都是基于实验经验值,一开始鱼翅用的是图中的角度 5 的 Tan(),各位读者有兴趣也可以自己尝试找找适合自己业务的这个值。
➨7)对于文件末尾的处理,鱼翅也是由大量实验结果分析得出:即发送一个很小的剩余文件尾(哪怕只有几个字节),其所带来的额外开销,例如 RTT 延迟也跟较大的分片差不多,因此鱼翅方案对于剩余文件大小小于当前计算出的最新分片大小的 X 倍时,就会将剩余文件内容全部放到最后一个分片中发送,避免出现“小尾巴大开销”的浪费。
讲到这里,鱼翅的核心思想已经陈述过半。相信经验丰富的读者们一定设计过比 SSCM 复杂的多状态机,但是这里需要强调的是,这个模块的策略及其核心参数的最终值都是对成百上千次实验结果的分析后逐渐得出的,这个过程很苦、也很美妙。
标签:重传,网络,即时通讯,传输速度,传输,鱼翅,IM,分片,大小 来源: https://www.cnblogs.com/weikeyun11/p/16523636.html