TCP / IP-over-Ethernetnetworking中的延迟

你会推荐什么资源(书籍,网页等):

  • 解释TCP / IP-over-Ethernetnetworking中等待时间的原因;
  • 提及用于寻找导致延迟的事物的工具(例如, netstat -s某些条目);
  • build议调整Linux TCP堆栈以减lessTCP延迟(Nagle,套接字缓冲区等)。

我知道的最接近的是这个文件 ,但是相当简短。

或者,欢迎您直接回答上述问题。

编辑为了清楚起见,问题不仅仅是关于“exception”的延迟,而是关于一般的延迟。 此外,它特别针对TCP / IP-over-Ethernet而不是其他协议(即使它们具有更好的延迟特性)。

关于内核可调参数的延迟,请记住:

 echo 1 > /proc/sys/net/ipv4/tcp_low_latency 

从文档 :

如果设置,则TCP堆栈作出的决定偏好较低的延迟而不是较高的吞吐量。 默认情况下,这个选项没有设置,这意味着更高的吞吐量是首选。 应该更改这个默认值的应用程序的例子是一个Beowulf计算集群。 默认值:0

您也可以在您的应用程序中禁用Nagle的algorithm(这将cachingTCP输出,直到最大的段大小),如下所示:

 #include <sys/types.h> #include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <linux/tcp.h> int optval = 1; int mysock; void main() { void errmsg(char *msg) {perror(msg);exit(1);} if((mysock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { errmsg("setsock failed"); } if((setsockopt(mysock, SOL_SOCKET, TCP_NODELAY, &optval, sizeof(optval))) < 0) { errmsg("setsock failed"); } /* Some more code here ... */ close(mysock); } 

这个选项的“相反”是TCP_CORK ,它将“re-Nagle”数据包。 但是要小心,因为TCP_NODELAY可能并不总是按照你的期望来做,而且在某些情况下会损害性能。 例如,如果您正在发送批量数据,则需要最大化每个数据包的吞吐量,因此请设置TCP_CORK 。 如果您有一个需要立即交互的应用程序(或者响应远大于请求,否定开销),请使用TCP _NODELAY 。 另外,这个行为是Linux特有的,BSD可能不同,所以要注意pipe理员

确保您的应用程序和基础设施进行彻底的testing。

根据我的经验,在其他健康的高速networking上出现exception延迟的最主要原因是TCP Windowing( RFC1323,第2节 )故障,在TCP Delayed Acks ( RFC1122第4.2.3.2 节 )的故障中密切相关。 这两种方法都是对TCP的改进,以更好地处理高速networking。 当他们打破,速度下降到非常缓慢的水平。 这些情况下的故障会影响较大的传输(认为是备份stream),在这些情况下,极端事务性的小stream量(平均数据传输低于MTU大小,并且存在大量的后退)将受这些影响较小。

同样,当两个不同的TCP / IP协议栈正在交谈时,我已经看到了这两个问题中最大的问题。 如Windows / Linux,2.4-Linux / 2.6-Linux,Windows / NetWare,Linux / BSD。 喜欢喜欢的作品非常非常好。 微软重写了Server 2008中的Windows TCP / IP堆栈,该堆栈介绍了Server 2003中不存在的Linux互操作性问题(我相信这些问题已得到解决,但我不能100%确定)。

关于延迟或select性确认的确切方法的不一致可能导致如下情况:

  192.168.128.5→192.168.128.20:1500b有效载荷,SEQ 1562
 192.168.128.5→192.168.128.20:1500b有效载荷,SEQ 9524
 [200ms通过]
 192.168.128.20→192.168.128.5:ACK 1562
 192.168.128.5→192.168.128.20:1500b有效载荷,SEQ 12025
 192.168.128.5→192.168.128.20:1500b有效载荷,SEQ 13824
 [200ms通过]
 192.168.128.20→192.168.128.5:ACK 12025 

由于所有的200ms超时(Windows默认延时定时器为200ms),所以吞吐量大打折扣。 在这种情况下,会话双方都无法处理TCP Delayed Ack。

TCP Windowing故障很难注意,因为它们的影响可能不太明显。 在极端的情况下,Windowing完全失败,当传输大于10KB的任何东西时,你会得到packet-> ack-> packet-> ack-> packet-> ack,这样会很慢,并且会放大链路上的基本延迟 。 难以检测的模式是当双方不断重新协商其窗口大小,并且一方(发送方)未能尊重需要几个数据包处理的协商,才能继续传送数据。 这种故障在Wireshark踪迹中以红色闪烁的灯光显示,但performance为吞吐量低于预期。


正如我所提到的,上述情况往往困扰着大量的转移。 像stream媒体video或备份stream的stream量可以真正钉在他们身上,以及非常大的文件(如Linux发行版ISO文件)的简单下载。 正如所料,TCP Windowing被devise为解决基本延迟问题的一种方法,因为它允许stream水线化数据; 您不必等待发送每个数据包的往返时间,只需发送一个大块,等待一个ACK就可以发送更多。

也就是说,某些networking模式不能从这些解决方法中受益。 高度事务性的小数据传输,例如数据库生成的小数据传输, 正常情况下会受到线上延迟的影响。 如果RTT很高,那么这些工作负载将会受到很大的影响,因为大型的stream媒体工作负载将会受到很大的影响。

这个问题有很多答案。

请记住TCP如何工作。 客户端发送SYN,服务器回答SYN / ACK,客户端回答ACK。 一旦服务器收到ACK,它现在可以发送数据。 这意味着您必须等待往返时间(RTT)的2倍才能发送第一位有意义的数据。 如果你有500毫秒的RTT,那么从一开始就有1秒延迟。 如果会话是短暂的,但很多,这会造成很多延迟。

一旦会话build立,服务器发送必须由客户端确认的数据单元。 服务器在需要确认第一个数据单元之前,只能在野外发送这么多的数据。 这也可能造成延迟。 如果数据单元被丢弃,则必须从那里接收传输,因此会产生额外的延迟。

在IP级别上,你有碎片(尽pipe现在很less见)。 如果您发送1501个字节的帧,而另一侧只支持1500的MTU,则您将发送一个额外的IP数据包用于最后一位数据。 这可以通过使用巨型帧来克服。

提高TCP / IP吞吐量的最佳方法是尽可能减less延迟,尽可能避免传输错误。 我不知道任何内核的调整,但我相信有人会。

在WAN的情况下,引入延迟的主要因素是光速。 穿越北美需要大约36.2ms理论最小值

在几秒钟内沿光纤电缆的单程:

  • $ _DISTANCE_IN_MILES *(Cable_Refraction / SPEED_OF_LIGHT)

将乘以1000的次数从秒转换为毫秒。 双倍来回:

  • $ _DISTANCE_IN_MILES *(Cable_Refraction / SPEED_OF_LIGHT)* 1000 * 2

华盛顿特区洛杉矶的延迟时间如下:

  • 2308 *(1.46 / 186000)* 1000 * 2 = 36.23311ms

  • 光速(英里/秒)= 186000
  • 光缆折射率= 1.46
  • 距离(从英里DC到洛杉矶)= 2308

更多关于公式

可能不是你要找的答案:广域网延迟的主要原因是光速(速度太慢!)。 另外,一路上有一个很大的缓冲区的饱和链路往往会造成令人印象深刻的延迟

请参阅以下网站: http : //www.29west.com/docs/THPM/index.html

TCP是一种端到端(或客户端到客户端)协议,假设中间的networking损失很less。 有关更强大的协议,请参阅X.25 。 因此,您将只对客户端(不是networking)上的协议参数拥有最大的控制权。

以太网是一个局域网(LAN)(尽pipe这个定义在过去的十年中也被广泛的扩展到包括广域网),除非在共享网段上面对70%或更多的stream量。 在现代以太网中,重发是很less发生的事情,但是现在几乎所有的以太网段都是交换的。

所以在局域网的延迟方面,拥塞是你最大的敌人。 但是,那么比起单纯的延迟,你就有更严重的问题。

如果您对通信协议的延迟问题非常认真,那么您应该考虑采用分组交换而不是虚拟电路协议,例如UDP或RTMP。