移动网络有如下几个不稳定特点(“高时延”、“易抖动”、“通道窄”)
1)移动状态网络信号不稳定,高时延、易抖动丢包、通道狭窄;
2)移动状态网络接入类型和接入点变化频繁;
3)移动状态用户使用高频化、碎片化、非WIFI流量敏感;
移动网络为什么慢?
1.DNS解析,这个在有线互联网上司空见惯的服务,在移动互联网上变成了一种负担,一个往复最少1s,还别提遇到移动运营商DNS故障时的尴尬。
2.链路建立成本暨TCP三次握手,在一个高时延易抖动的网络环境,并且大部分业务数据交互限于一个HTTP的往返,建链成本尤其显著。
3.TCP协议层慢启动、拥塞控制、超时重传等机制在移动网络下参数设定的不适宜
4.不好的产品需求规定或粗放的技术方案实现,使得不受控的大数据包、频繁的数据网络交互等,在移动网络侧TCP链路上传输引起的负荷。
5.不好的协议格式和数据结构设计,使得协议封装和解析计算耗时、耗内存、耗带宽,甚至协议格式臃肿冗余,使得网络传输效能低下。
6.不好的缓存设计,使得数据的加载和渲染计算耗时、耗内存、耗带宽
移动联网快的四个方法(快链路、轻往复、强监控、多异步)
1.快链路
我们需要有一条(相对)快速、(相对)顺畅、(相对)稳定的网络通道承载业务数据的传输,这条路的最好是传输快、不拥堵、带宽大、收费少。
1.1. TCP/IP协议栈参数调优
比较复杂繁多,可自行百度 Google 具体详细内容。
1.1.1 控制传输包大小
控制传输包的大小在1400字节以下。我们设定1400这个阈值,目的是减少往复,提高效能。因为TCP/IP网络中也有类似高速限高的规定,如果在超限时想要继续顺畅传输,要么做IP分片要么把应用数据拆分为多个数据报文(意指因为应用层客户端或服务器向对端发送的请求或响应数据太大时,TCP/IP协议栈控制机制自动将其拆分为若干独立数据报文发送的情况,后面为简化讨论,都以IP分片这个分支为代表,相关过程分析和结论归纳对二者均适用)。而一旦一个数据报文发生了IP分片,便会在数据链路层引入多次的传输和确认,加上报文的拆分和拼接开销,令得整个数据包的发送时延大大增加,并且,IP分片机制中,任何一个分片出现丢失时还会带来整个IP数据报文从最初的发起端重传的消耗。有点枯燥了,我们从一些基础概念开始逐步深入理解:
a.【以太网】
这个术语一般是指数字设备公司(Digital Equipment Corp.)、英特尔公司(I n t e l Corp.)和X e r o x公司在1 9 8 2年联合公布的一个标准,它是当今TCP/IP采用的主要网络技术。以太网采用一种称作C S M A/C D的媒体接入方法,其意思是带冲突检测的载波侦听多路接入(Carrier Sense,Multiple Access with Collision Detection)。随着以太网技术的不断演进,传输速率已由最初的10 Mb/s发展到如今100Mb/s、1000Mb/s、10000Mb/s等。
我们现在使用的TCP/IP网络协议,基本上都在以太网上传输,数据被封装在一个个以太网包中传递,这些以太网包就是那一辆辆运猪的大卡车。以太网包的封装格式可以参考下图,很容易看出以太网包能传输的有效“数据”大小在46~1500字节之间。如果我们把以太网看做是运猪的高速公路,能承载有效数据的最大值看作是高速路上隧道的限高,那么这个限高在TCP/IP协议中学名是MTU(Maximum Transmission Unit,最大传输单元)。MTU属于链路层制定的逻辑(并非物理)特性限制,所谓无规矩不成方圆。

【以太网的封装格式(RFC 894)】
b.【TCP/IP数据报】
TCP/IP数据报被封装在以太网包的“数据”中,通过下图可以看到,一个IP数据报包括IP包头、TCP包头和TCP数据三个部分,其中两个包头分别用于IP层和TCP层的报文传输控制,可以理解为运猪的大卡车和猪笼。TCP数据则是有效载荷。

【TCP数据在IP数据报中的封装】
我们再来详细看看IP数据报,如图【IP数据报格式及首部中的各字段】所示,一个标准IP数据报中,IP包头大小为20字节,如果加上可选项,则IP包头最大可以达到60字节。

TCP数据报如图【TCP数据报格式及首部中的各字段】所示,一个标准TCP包头大小为20字节,如果加上可选项,则最大也可以达到60字节。

【TCP数据报格式及首部中的各字段】
c.【TCP MSS】
TCP MSS(TCP Maximum Segment Size,TCP最大报文段长度,后面均简称MSS)表示TCP/IP协议栈一次可以传往另一端的最大TCP数据长度,注意这个长度是指TCP报文中的有效“数据”(即应用层发出的业务数据)部分,它不包括TCP报文包头部分,我们可以把它理解为卡车能装运生猪的最大数量或重量。它是TCP选项中最经常出现,也是最早出现的选项,占4字节空间。
MSS是在建立TCP链接的三次握手过程中协商的,每一方都会在SYN或SYN/ACK数据报文中通告其期望接收数据报文的MSS(MSS也只能出现在SYN或SYN/ACK数据报中),说是协商,其实也没太多回旋的余地。如果协商过程中一方不接受另一方的MSS值,则TCP/IP协议栈会选择使用默认值:536字节。
有了以上的基础知识,我们就能比较清晰的描述出以太网、MTU、TCP/IP数据报文和MSS之间的关系了,如【图七TCP/IP数据报、MTU/MSS在以太网格式中的关系】所示,MTU和MSS关系用公式表达就是:
MTU=IP包头+TCP包头+MSS;

【TCP/IP数据报、MTU/MSS在以太网格式中的关系】
注:FCS(Frame Check Sequence)是指帧校验值;
实际上MSS值太小或太大都不合适。
太小比如设为1字节,那么为了传输1个字节的数据,得搭上IP包头的20字节和TCP包头的20字节,如果再加上链路层、物理层的其它开销,显然效率低下不够环保,这就如同卡车跑一趟只拉一头肥猪一样,相当坑。
MSS是不是越大越好呢,这也符合我们的正常思维逻辑,就好比养猪场和买家都希望卡车一趟能多运几头肥猪,可以加快资源周转效率。但实际情况是MSS如果设得太大,封装的数据过多,不但传输时延会增加,还很可能因为超过MTU的限制,使得在IP层传输过程中发生分片,接受方在处理IP分片包所消耗的资源和处理时间都会增大,前面也提到过,如果IP分片在传输中出现分片丢失,哪怕只是丢失一个分片,都会引起整个IP数据报的重传,这是因为IP层本身没有设计超时重传机制,有兴趣可以研读《TCP/IP详解卷一:协议》了解详细细节。由此可以想见网络开销会因此大大增加。
TCP/IP协议设计者是不希望分片出现的,现在有点明白前面说MSS协商回旋余地不大的含义了吧。另外,MSS同滑动窗口和拥塞控制也有关联,后续谈到相关话题时我们再细聊。
d.【IP分片】
IP数据报文传输过程中,任何传输路径上节点的IP层在接收到一份要发送的IP数据报文时,首先会通过路由选路判断应从本地哪个网络接口把IP数据报转发出去,随后查询获取该网络接口的MTU,如果IP数据报文长度超过了这个MTU,且该数据报文没有设置DF(Don’t Frament,不要分片,非缺省值)标志位,就得做IP分片,即把接收到的IP数据报文拆分成多个更小(不超过该接口MTU)的IP数据报文继续传输,并且,分片的数据可能在路上会被再次分片,分片到达最终目的地后会按顺序重新组装还原,上图【IP数据报格式及首部中的各字段】中3位标志和13位片偏移就是用来干这个的。
为了避免IP分片,TCP/IP协议设计者在TCP层实现了MSS协商机制,设想如果最终确定的MSS小于路由路径中最小的那个MTU,那么就能避免IP分片的发生。
在TCP链接三次握手过程中,网络通讯的两个端点在SYN和SYN/ACK数据报文中分别把自己出口MSS发给对端,以便对方了解自己的“限高”水平,最终控制发出的应用数据报文大小,达到避免IP分片的目的。
如果运气好,路由路径上的路由设备会积极参与三次握手过程中MSS协商机制,一旦发现自己出口的MSS比数据报文中的那个小,就会主动修改数据报文中的MSS,这样整个路由链路端到端这条“高速路”的整体“限高”水平就准确清晰了。
通过下图【TCP MSS协商过程】,可以了解上述TCP MSS的协商过程。注意,这个“完美”方案需要运气好才行。因为中间路由设备五花八门,不能支持或者不愿支持MSS协商的情况时有发生。想让大伙都积极支持协商的美好愿望,就如同满怀对全世界各国*官员实施财产公示的期许,结果是一样一样的。

【TCP MSS协商过程】
至此,我们可以得出如下结论,TCP/IP数据报文大小超过物理网络层的限制时,会引发IP分片,从而增加时空开销。
因此,设定合理的MSS至关重要,对于以太网MSS值建议是1400字节。什么,你的数学是体育老师教的吗?前面说以太网最大的传输数据大小是1500字节,IP数据报文包头是20字节,TCP报文包头是20字节,算出来MSS怎么也得是1460字节呀。如果回答是因为很多路由设备比如CISCO路由器把MSS设定为1400字节,大伙肯定不干,回忆一下IP和TCP的数据报包头都各有40字节的可选项,MTU中还需要为这些可选项留出空间,也就压缩了MSS的空间。要是再追问为啥这个值不是1380字节,那就有点过分了。
那么问题来了,控制“限高”哪种方案才最强。我们尝试探讨一下。
首先,可以在我们自己IDC内将各种路由交换设备的MSS设定小于或等于1400字节,并积极参与TCP三次握手时的MSS协商过程,期望达到自动控制服务器收发数据报文大小不超过路径最小MTU从而避免IP分片。这个方案的问题是如果路由路径上其它设备不积极参与协商活动,而它的MTU(或MSS设置值)又比较low,那就白干了。这就好比国家制定了一个高速沿途隧道限高公示通告标准,但是某些地方*就是不告诉你,没辙。
其次,可以在业务服务中控制应用数据请求/响应的大小在1400字节以***:也无法根本避免前述方案中间路由MTU/MSS low的问题),在应用层数据写入时就避免往返数据包大小超过协商确定的MSS。但是,归根到底,在出发前就把数据拆分为多个数据报文,同IP分片机制本质是相同的,交互响应开销增加是必然的。考虑到人在江湖,安全第一,本方案从源头上控制,显得更实际一些。
对应到前面的快乐运猪案例,就是要么在生猪装车之前咱们按照这条路上的最低限高来装车(问题是怎么能知道整个路上的最低限高是多少),要么按照国家标准规定允许的最小限高来装车,到这里,肥猪们终于可以愉快的上路了,风和日丽,通行无阻,嗯,真的吗?
1.1.2放大TCP拥塞窗口
把TCP拥塞窗口(cwnd)初始值设为10,这也是目前Linux Kernel中TCP/IP协议栈的缺省值。放大TCP拥塞窗口是一项有理有据的重要优化措施,对移动网络尤其重要,我们同样从一些基本理论开始逐步深入理解它。
TCP是个传输控制协议,体现控制的两个关键机制分别是基于滑动窗口的端到端之间的流量控制和基于RTT/RTO测算的端到网络之间的拥塞控制。
流量控制目标是为了避免数据发送太快对端应用层处理不过来造成SOCKET缓存溢出,就像一次发了N车肥猪,买家那边来不及处理,然后临时囤货的猪圈又已客满,只好拒收/抛弃,相关概念和细节我们不展开了,有兴趣可以研读《TCP/IP详解卷一:协议》。
拥塞控制目标是在拥塞发生时能及时发现并通过减少数据报文进入网络的速率和数量,达到防止网络拥塞的目的,这种机制可以确保网络大部分时间是可用的。拥塞控制的前提在于能发现有网络拥塞的迹象,TCP/IP协议栈的算法是通过分组丢失来判断网络上某处可能有拥塞情况发生,评判的具体指标为分组发送超时和收到对端对某个分组的重复ACK。在有线网络时代,丢包发生确实能比较确定的表明网络中某个交换设备故障或因为网络端口流量过大,路由设备转发处理不及时造成本地缓存溢出而丢弃数据报文,但在移动网络中,丢包的情况就变得非常复杂,其它因素影响和干扰造成丢包的概率远远大于中间路由交换设备的故障或过载。比如短时间的信号干扰、进入一个信号屏蔽的区域、从空闲基站切换到繁忙基站或者移动网络类型切换等等。网络中增加了这么多不确定的影响因素,这在TCP拥塞控制算法最初设计时,是无法预见的,同时,我们也确信未来会有更完善的解决方案。
拥塞控制是TCP/IP协议栈最经典的和最复杂的设计之一,互联网自我牺牲的利他精神表露无遗,设计者认为,在拥塞发生时,我们应该减少数据报文进入网络的速率和数量,主动让出道路,令网络能尽快调整恢复至正常水平。
拥塞控制机制包括四个部分:
a.慢启动;
b.拥塞避免;
c.拥塞发生时的快速重传;
d.快速恢复;
慢启动这项措施的缘起是,当新链接上的数据报文进入一个拥塞状况不可预知的网络时,贸然过快的数据发送可能会加重网络负担,就像养猪场每天都会向很多买家发车送肥猪,但是出发前并不了解各条高速路上的拥堵情况,如果按照订单一口气全部发出去,会遇到两种情况,一是高速很顺畅,很快到达(此时流量控制可能要干预了);二是高速本身就有些拥堵,大批卡车上路加剧了拥堵,并且肥猪们堵在路上,缺衣少食饿瘦了买家不干,风餐露宿冻死了卖家吃亏,重新发货还耽误时间,并且,用于重新发货的货车加入高速则进一步加重了拥堵的情况。作为一个充满社会良知精神的养猪场,我们肯定不愿意贸然增加高速的负担。
接下来进入理论知识介绍部分
TCP是一个可靠传输协议,基础是发送-应答(ACK)式确认机制,如此往复。如图【TCP链接建立、传输和关闭示意】,可以了解这种发送-应答式工作的基本流程,如果再结合流量控制、拥塞控制和超时重传等机制,会有很多变种case,整个协议栈因而显得比较复杂。
慢启动顾名思义,就是把(网络链路数据报文传输)启动的速度放慢一些。方法其实也挺简单,TCP发送方维护了两个参数用于控制这个过程,它们分别是拥塞窗口(cwnd,Congestion Window)和慢启动门限(ssthresh,Slow Start Threashold),具体算法如下:
1)TCP链接建立好以后,cwnd初始化1,单位是链接建立过程中协商好的对端MSS,1代表一次可以发送1*MSS个字节。ssthresh初始化为65535,单位是字节;
2)每当收到一个ACK,cwnd++,cwnd呈线性上升,发送方此时输出数据量不能超过cwnd和接收方通告的TCP窗口(这个概念我们在后面的章节中会介绍)大小;
3)每当经过一个RTT(Round Trip Time,网络往返时间),cwnd=cwnd*2,cwnd呈指数让升,同样发送方此时输出数据量不能超过cwnd和接收方通告的TCP窗口大小;
4)ssthresh(slow start threshold)是一个上限,当cwnd>=ssthresh时,就进入“拥塞避免”算法;
介绍一下RTT,它是Round Trip Time(网络往返时间)的简写,简单的理解就是一个数据报文从发送出去到接收到对端ACK确认的时间(这样描述其实不够严谨,因为我们没有展开数据报文发送和对端ACK确认的各种复杂case)。RTT是TCP超时重传机制的基础,也是拥塞控制的关键参数,准确的估算出RTT具有伟大的现实意义,同时也是一项相当艰巨复杂的任务。计算机科学先辈们在持续完善RTT的计算方法,从最初RFC793中描述的经典算法,到Karn/Partridge算法,最后发展到今天在使用的Jacobson/Karels算法,如有兴趣可自行以深入研究。
通过下图【慢启动过程示意】,可以更直观的理解慢启动的过程,经过两个RTT,cwnd已经由初始值1演化为4:即在接收方通告窗口大小允许的情况下,可以连续发送4个数据报文,然后继续指数增长,这么看来,慢启动一点都不慢。

【图十慢启动过程示意】
注:示意图中三个RTT大括弧逐渐变大不是因为RTT数值变大,而是要示意包含的数据报文变多。
Linux Kernel从3.0开始采用了把cwnd初始化为10个MSS,而在此之前,Linux Kernel采用了RFC3390的规定,cwnd是根据MSS的值来动态变化的。
简单来说,cwnd初始化为10,就是为了允许在慢启动通过往复RTT“慢慢”提升拥塞窗口前,可以在第一个网络传输回合中就发送或接收14.2KB(1460 10 vs 5.7KB 1460 4)的数据。这对于HTTP和SSL来讲是非常重要的,因为它给了更多的空间在网络交互初始阶段的数据报文中填充应用协议数据。
对于移动APP,大部分网络交互都是HTTP并发短链接小数据量传输的形式,如果服务器端有10KB+的数据返回,采用过去的慢启动机制时,效率会低一些,大概需要2~3个RTT才能完成数据传输,反应到用户体验层面就是慢,而把拥塞窗口cwnd初始值提升到10后,在大多数情况下都能在1个RTT的周期内完成应用数据的传输,这在移动网络这样的高时延、不稳定、易丢包的场景下,显得尤其意义重大。(让慢启动歇息一会,在某些特定情况下可以提高速率)
3.1.1.3调大SOCKET读写缓冲区
把SOCKET的读缓冲区(亦可称为发送缓冲区)和写缓冲区(亦可称为接收缓冲区)大小设置为64KB。在Linux平台上,可以通过setsockopt函数设置SO_RCVBUF和SO_SNDBUF选项来分别调整SOCKET读缓冲区和写缓冲区的大小。
这两个缓冲区跟我们的TCP/IP协议栈到底有怎么样的关联呢。我们回忆一下图【TCP数据报格式及首部中的各字段】,里面有个16位窗口大小,还有我们前面提到的流量控制机制和滑动窗口的概念。在正式详细介绍之前,假设我们站在猪场老板的角度看一下,读缓冲区就好比买家用来囤货的临时猪圈,如果货到了买家使用部门来不及处理,就先在这里临时囤着,写缓冲区就好比养猪场根据订单装好车准备发货,如果买家说我现在可以收货便可速度发出,有点明白了吧。下面详细展开探讨:
a.【TCP窗口】
整个TCP/IP协议体系是经典的分层设计,TCP层与应用层之间衔接的部分,就是操作系统内核为每个TCP链路维护的两个缓冲区,一个是读缓冲一个是写缓冲。从数据结构角度讲,这两个缓冲区是环形缓冲区。
读缓冲肩负的使命是把接收到并已ACK(确认)过的TCP报文中的数据缓存下来,由应用层通过系统接口读取消费。就好比买家内部会分原料采购部门和产品加工部门,采购部门收到肥猪后先送到临时猪圈好吃好喝供着,加工部门需要的时候就会拎着屠刀过来提猪。
写缓冲肩负的重任是缓存应用层通过系统接口写入的要发送的数据,然后由TCP/IP协议栈根据cwnd、ssthresh、MSS和对端通告的TCP窗口等参数,择机把数据分报文段发往对端读缓冲。想要在拥塞控制等相关参数都允许的条件下连续发送数据报文,尚需对端通告的TCP窗口大小能够容纳它们。就好比猪场老板根据买家订单发货,先调配若干辆卡车,根据高速的限高要求装上肥猪,然后再考虑高速的顺畅情况来分批发货,货可以陆续上路,但还有一个重要前提是发货前买家通告的临时猪圈空间是足够容纳这些肥猪的。
TCP窗口是用于在接收端和发送端之间动态反映接收端读缓冲大小的变化,它的初始值就是读缓冲区设定的值,单位是字节,这个数字在TCP包头的16位窗口大小字段中传递,最大65535字节,如果嫌不够大,在TCP选项中还有一个窗口扩大的选项可供选择。
概括而言,TCP窗口的作用是量化接收端的处理能力,调控发送端的传输节奏,通过窗口的伸缩,可以自如的调节发送端的数据发送速率,从而达到对接收端流量控制的目的。
b.【滑动窗口】
客户端和服务器在TCP链接建立的三次握手过程中,会根据各自接收缓冲区大小通告对方TCP窗口大小,接收方根据自己接收缓冲区大小初始自己的“接收窗口”,发送方根据对端通告的TCP窗口值初始化一个对应的“发送窗口”,接收窗口在此端的接收缓冲区上滑动,发送窗口在彼端的发送缓冲区上滑动。因为客户端和服务器是全双工,同时可收可发,故我们有两对这样的窗口在同时工作。
既然是滑动窗口,就意味着可以滑动、伸缩,下图【TCP窗口边沿移动】展示了这些情况,注意TCP/IP协议栈规定TCP窗口左边沿只能向右滑动,且TCP的ACK确认模式也在机制上禁止了TCP窗口左边沿向左移动。与窗口滑动相关术语有三个:
1)TCP窗口左边沿向右边沿靠近称为窗口合拢,发生在数据被发送和确认时。如果左右边沿重合时,则形成一个零窗口,此时发送方不能再发送任何数据;
2)TCP窗口右边沿向右移动称为窗口张开,也有点类似窗口向右侧横向滑动。这种现象发生在接收方应用层已经读取了已确认过的数据并释放了TCP接收缓冲区时;
3)TCP窗口右边沿向左移动称为窗口收缩,RFC强烈建议避免使用这种方式;

【TCP窗口边沿移动】
我们再来看看滑动窗口与SOCKET缓冲区如何结合使用。假设一个客户端设置了16个单位的读缓冲区,编号是015,服务器也相应的设置了16个单位的写缓冲区,编号是015。在TCP链接建立的时候,客户端会把自己的读缓冲大小16通告给服务器,此时在客户端和服务器就维护了一对收发窗口。在下图【服务器TCP发送窗口示意】展示了服务端发送缓冲区和其上的滑动窗口,其中大的黑色边框就是著名的滑动窗口。
【服务器TCP发送窗口示意】
发送缓冲和发送窗口一共区隔出四个部分:
1)已发送并收到ACK确认的数据(即已成功到达客户端),单元格边框以粉色标识;
2)已发送还未收到ACK确认的数据(即发送但尚未能确认已被客户端成功收到),单元格边框以蓝色标识;
3)处于发送窗口中还未发出的数据(即对端接收窗口通告还可容纳的部分),单元格边框以绿色标识;
4)处于发送窗口以外还未发出的数据(即对端接收窗口通告无法容纳的部分),单元格边框以黄色标识;
为了更好的理解滑动窗口的变化过程,可以观察下图【TCP滑动窗口变迁示例】,它向我们展示了一个服务器向客户端发送数据时读写窗口的变化过程:

【图TCP滑动窗口变迁示例】
1)客户端通告了一个360字节的TCP窗口并在自己的读缓冲区初始化该窗口,服务器在它的写缓冲区初始化了这个窗口;
2)服务器发送120字节到客户端,服务器发送窗口此时包括了两部分,120字节为等待ACK确认的数据、240字节为等待发送的数据,窗口大小为360字节不变;
3)客户端收到120字节数据,放入接收缓冲区,此时应用层马上读取了头40字节,接收窗口因此调整为280(360-120+40)字节,接收窗口先合拢,然后张开。客户端回复ACK确认收到120字节数据,并且通告接收窗口调整为280字节;
4)服务器收到客户端的ACK确认,发送窗口也先发生合拢,随后根据客户端通告的新接收窗口大小,重新调整发送窗口,此时发送窗口又张开至280字节;
5)服务器发送240字节到客户端,服务器发送窗口此时包括了两部分,240字节为等待ACK确认和40字节等待发送的数据,窗口大小为280字节不变;
6)客户端收到240字节数据,放入接收缓冲区,此时应用层又读取了头80字节,接收窗口因此调整为120(280-240+80),接收窗口先合拢,然后张开。客户端回复ACK确认收到240字节数据,并且通告接收窗口调整为120字节;
7)服务器收到客户端的ACK确认,发送窗口也先发生合拢,随后根据客户端通告的新接收窗口大小,重新调整发送窗口,此时发送窗口又张开至120字节;
8)服务器发送120字节到客户端,服务器发送窗口此时仅包括一部分,即120字节等待ACK确认的数据;
9)客户端收到120字节数据,放入接收缓冲区,接收窗口因此调整为0(120-120),接收窗口合拢为0。客户端回复ACK确认收到120字节数据,并且通告接收窗口调整为0字节;
10)服务器收到客户端的ACK确认,发送窗口也发生合拢,随后根据客户端通告的新接收窗口大小,重新调整发送窗口,此时因为接收窗口为0,发送窗口保持合拢状态;
提升TCP吞吐量,最佳状态是在流量控制机制的调控下,使得发送端总是能发送足够的数据报文填满发送端和接收端之间的逻辑管道和缓冲区。其中逻辑管道的容量有专门的学名叫BDP(Bandwidth Delay Product,带宽时延乘积,BDP=链路带宽*RTT),在一个高带宽低时延的网络中,TCP包头中的16位窗口大小可能就不够用了,需要用到TCP窗口缩放选项,在RFC1323中定义,有兴趣可以研究一下。
3.1.1.4调大RTO(Retransmission TimeOut)初始值
将RTO(Retransmission TimeOut)初始值设为3s。
TCP为每一个报文段都设定了一个定时器,称为重传定时器(RTO),当RTO超时且该报文段还没有收到接收端的ACK确认,此时TCP就会对该报文段进行重传。当TCP链路发生超时时,意味着很可能某个报文段在网络路由路径的某处丢失了,也因此判断此时网络出现拥塞的可能性变得很大,TCP会积极反应,马上启动拥塞控制机制。
RTO初始值设为3s,这也是目前Linux Kernel版本中TCP/IP协议栈的缺省值,在链路传输过程中,TCP协议栈会根据RTT动态重新计算RTO,以适应当前网络的状况。有很多的网络调优方案建议把这个值尽量调小,但是,我们开篇介绍移动网络的特点之一是高时延,这也意味着在一个RTT比较大的网络上传输数据时,如果RTO初始值过小,很可能发生不必要的重传,并且还会因为这个事件引起TCP协议栈的过激反应,大炮一响,拥塞控制闪亮登场。
3.1.1.5禁用TCP快速回收
TCP快速回收是一种链接资源快速回收和重用的机制,当TCP链接进入到TIME_WAIT状态时,通常需要等待2MSL的时长,但是一旦启用TCP快速回收,则只需等待一个重传时间(RTO)后就能够快速的释放这个链接,以被重新使用。Linux Kernel的TCP/IP协议栈提供了一组控制参数用于配置TCP端口的快速回收重用,当把它们的值设置为1时表示启用该选项: