TCP协议之网络延时

影响TCP 网络时延的因素
硬件速度
网络和服务器的负载
请求和响应报文的尺寸
客户端和服务器之间的距离
TCP 协议的技术复杂性
TCP协议产生的时延
TCP 链接创建握手;
TCP 慢启动拥塞控制;
数据汇集的 Nagle 算法;
用于捎带确认的 TCP 延迟确认算法;
TIME_WAIT 时延和端口耗尽。
TCP链接创建
TCP链接的创建,须要经历3个报文的交互过程,沟通相关链接参数,这个过程称为三次握手(three-way handshake)。算法

所以,若是在每次发送数据以前,都从新创建一次TCP链接,那么创建链接的耗时将对性能产生较大的影响(特别是在发送少许数据的状况下)。shell

 

三次握手四次挥手(参考自coolshell)缓存

优化方法服务器

创建长链接,屡次数据的发送复用同一条链接。网络

TCP慢启动
若是在发送方和接收方之间存在多个路由器和速率较慢的链路,此时多个发送方一开始便向网络发送多个报文段,因为受网络传输和服务端处理能力的影响,一些中间路由器必须缓存分组,并有可能最终耗尽存储器的空间,于是更多的报文发送将使网络出现拥塞。tcp

TCP慢启动(slow start),就是用于防止因特网的忽然过载和拥塞的一种流量控制机制。函数

慢启动为发送方的TCP增长了一个窗口:拥塞窗口(congestion window),简称cwnd。性能

刚创建链接时,拥塞窗口被初始化为1个报文段。每收到一个ACK,拥塞窗口就增长一个报文段。发送方取拥塞窗口与接收方通告窗口中的最小值做为发送上限。优化

也就是说,TCP链接会随着时间进行自我“调谐”,起初会限制链接的最大速度,若是数据成功传输,会随着时间的推移提升传输的速度。操作系统

注:拥塞窗口是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。(和滑动窗口同样么?)

优化方法

采用长链接,避免每次创建链接后的慢启动。

Nagle算法
在广域网上,小分组会增长网络拥塞出现的可能性。Nagle算法(根据其发明者John Nagle命名)旨在收集这些小分组,以一个分组的方式发出去,以提升网络效率。

该算法要求一个TCP链接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达以前不能发送其余的小分组。

该算法的优越之处在于它是自适应的:确认到达得越快,数据也就发送得越快。

Nagle 算法会引起如下性能问题

当报文没法填满一个分组时,须要等待其余额外数据;
Nagle算法会阻止数据的发送,直到有确认分组抵达为止,但确认分组自身会被延迟确认算法延迟 100 ~ 200 毫秒。
算法伪代码

if there is new data to send
  if the window size >= MSS and available data is >= MSS
    send complete MSS segment now
  else
    if there is unconfirmed data still in the pipe
      enqueue data in the buffer until an acknowledge is received
    else
      send data immediately
    end if
  end if
end if
优化方法

对于实时性要求较高的应用场景,能够经过设置TCP_NODELAY参数来关闭Nagle算法,提升性能。

延时确认算法
一般TCP在接收到数据时并不当即发送ACK;相反,它推迟发送,以便将ACK与须要沿该方向发送的数据一块儿发送。

有时称这种现象为数据捎带ACK,因为确认报文一般很小,因此TCP容许在发往相同方向的输出数据分组中对其进行“捎带”。

绝大多数实现采用的时延为200ms,也就是说,TCP将以最大200ms的时延等待是否有数据一块儿发送。

一般,延迟确认算法会引入至关大的时延。

优化方法

根据所使用操做系统的不一样,能够调整或禁止延迟确认算法。(这个方法我没尝试过)

TIME_WAIT状态
TIME_WAIT状态也称为2MSL等待状态。

当某个 TCP 端点关闭 TCP 链接时, 会在内存中维护一个小的控制块,用来记录最近所关闭链接的 IP 地址和端口号。

这类信息只会维持一小段时间,一般是所估计的报文段最大生存时间的的两倍(称为2MSL,一般为2分钟左右),以确保在这段时间内不会建立具备相同地址和端口号的新链接。

实际上,这个算法能够防止在两分钟内建立、关闭并从新建立两个具备相同IP地址和端口号的链接。

将 2MSL 的值取为 2 分钟是有历史缘由的。很早之前,路由器的速度还很慢,人们估计,在将一个分组的复制副本丢弃以前,它能够在因特网队列中保留最多一分钟的时间。如今,最大分段生存期要小得多了。

报文段最大生存时间MSL(Maximum Segment Lifetime),是指任何报文段被丢弃前在网络中的最长生存时间。

RFC 793 [Postel 1981c]指出MSL为2分钟。然而,实现中的经常使用值是30秒,1分钟或2分钟。

优化方法

打开tcp_tw_reuse,让程序能够重用处于TIME_WAIT状态的端口。若是使用tcp_tw_reuse,必需设置tcp_timestamps=1(默认值)。(这个对于快速重启某些服务颇有用,特别是服务端程序)
打开tcp_tw_recycle,让处于TIME_WAIT状态的套接字更快的回收。

贴一个nagle算法更详细的讲解

Nagle算法用于对缓冲区内的必定数量的消息进行自动链接。该处理过程(称为Nagling),经过减小必须发送的封包的数量,提升了网络应用程序系统的效率。

1. Nagle算法的规则

  (可参考tcp_output.c文件里tcp_nagle_check函数注释):
1)若是包长度达到MSS(MSS是最大分段大小Maxitum Segment Size ,MTU是最大传输单元Maxitum Transmission Unit),则容许发送;
2)若是该包含有FIN,则容许发送;
3)设置了TCP_NODELAY选项,则容许发送;
4)未设置TCP_CORK选项时,若全部发出去的包均被确认,或全部发出去的小数据包(包长度小于MSS)均被确认,则容许发送。
   对于规则4),就是说一个TCP链接上最多只能有一个未被确认的小数据包,在该分组的确认到达以前,不能发送其余的小数据包。若是某个小分组的确认被延迟了,那么后续小分组的发送就会相应的延迟。也就是说延迟确认影响的并不仅是被延迟确认的那个数据包,而是后续全部的应答包。

2. Nagle算法的门槛

   实际上Nagle算法并非很复杂,他的主要职责是数据的累积,实际上有三个门槛:

1)缓冲区中的字节数达到了必定量;

2)等待了必定的时间(通常的Nagle算法都是等待200ms);

3)紧急数据发送。

   这三个门槛的任何一个达到都必须发送数据了。通常状况下,若是数据流量很大,第二个条件是永远不会起做用的,但当发送小的数据包时,第二个门槛就发挥做用了,防止数据被无限的缓存在缓冲区不是好事情哦。 

3. Nagle算法的选项配置

   TCP_NODELAY和TCP_CORK都是禁用Nagle算法,只不过NODELAY彻底关闭而TCP_CORK彻底由本身决定发送时机。Linux文档上说二者不要同时设置。

3.1 TCP_NODELAY 选项

设置该选项: setsockopt(s,IPPRO_TCP,TCP_NODELAY,(const char*)&on,sizeof(int));
读取该选项: getsockopt(s,IPPRO_TCP,TCP_NODELAY,(char*)&on,&optlen);  

  

   默认状况下, 发送数据采用Nagle 算法. Nagle 算法是指发送方发送的数据不会当即发出,而是先放在缓冲区, 等缓存区满了再发出. 发送完一批数据后, 会等待接收方对这批数据的回应,而后再发送下一批数据。 

   Nagle 算法适用于发送方须要发送大批量数据, 而且接收方会及时做出回应的场合, 这种算法经过减小传输数据的次数来提升通讯效率。

   若是发送方持续地发送小批量的数据, 而且接收方不必定会当即发送响应数据, 那么Nagle算法会使发送方运行很慢。

3.2 TCP_CORK选项

   TCP连接的过程当中,默认开启Nagle算法,进行小包发送的优化。优化网络传输,兼顾网络延时和网络拥塞。这个时候能够置位TCP_NODELAY关闭Nagle算法,有数据包的话直接发送保证网络时效性。

   在进行大量数据发送的时候能够置位TCP_CORK关闭Nagle算法保证网络利用性。尽量的进行数据的组包,以最大mtu传输,若是发送的数据包大小太小则若是在0.6~0.8S范围内都没能组装成一个MTU时,直接发送。若是发送的数据包大小足够间隔在0.45内时,每次组装一个MTU进行发送。若是间隔大于0.4~0.8S则,每过来一个数据包就直接发送。

   Nagle组织包的长度是由系统决定的,有时候咱们知道咱们会每一个1分钟产生1字节,共1000字节。若是彻底由Nagle算法来发送的话,可能仍是会1字节1字节发送[这是一种极端状况,假设返回ACK时间不是很长]。这个时候首先设置TCP_CORK可以阻塞住TCP[尽可能阻塞住],等咱们write完1000字节以后,取消TCP_CORK,这个时候就可以将1000字节一次发出。

总结:

   TCP_CORK选项与TCP_NODELAY同样,是控制Nagle化的。      

1)打开TCP_NODELAY选项,则意味着不管数据包是多么的小,都当即发送(不考虑拥塞窗口)。
2)若是将TCP链接比喻为一个管道,那TCP_CORK选项的做用就像一个塞子。            

   设置TCP_CORK选项,就是用塞子塞住管道,而取消TCP_CORK选项,就是将塞子拔掉。            

   当TCP_CORK选项被设置时,TCP连接不会发送任何的小包,即只有当数据量达到MSS时,才会被发送。

   通常当数据传输完成时,一般须要取消该选项,以防被塞住,这样才可让不够MSS大小的包能及时发出去。

相关文章
相关标签/搜索