澄清Linux TCP窗口大小和延迟

前端之家收集整理的这篇文章主要介绍了澄清Linux TCP窗口大小和延迟前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我通过TCP通道发送数据时有延迟,我无法理解.该链路是1Gb链路,端到端延迟大约为40ms.在我目前的设置中,延迟(从一条消息到发送方用户空间到接收方用户空间的时间)可以达到100毫秒.

发件人套接字配置了TCP_NODELAY选项.发送器缓冲区(SO_SNDBUF)配置为8MB.接收缓冲区(SO_RCVBUF)也配置为8MB. Tcp窗口缩放已激活.

update-1:我使用zeromq 3.1.1中间件来传输数据.套接字配置,包括TCP_NODELAY标志由中间件执行.有些选项可以访问,例如rx和tx发出缓冲区大小但不是TCP_NODELAY.据我所知,TCP_NODELAY被激活以确保尽可能地发送数据.同时,实际的套接字发送和决定发送消息是在两个单独的线程中执行的.如果在发送批次中的第一条消息时有几条消息可用,则进行适当的批处理.

我使用tcpdump运行捕获,从中提取下面的帧.初始TCP握手后,发送方(172.17.152.124)开始发送数据.接收器和接收器的初始窗口大小是5840字节.发件人为5792字节.

我的问题是发送者发送两帧(#6和#7)然后停止,等待ack从接收器返回.据我所知,接收器的窗口大小没有达到,传输不应该停止(384字节未完成,初始接收窗口大小为5840字节).我开始认为我没有正确理解TCP是什么.有人可以帮忙澄清吗?

update-2:我的数据有效负载由一个幻数后跟一个时间戳组成.我通过比较有效载荷的时间戳和tcpdump放置的时间戳来隔离延迟的数据包.帧#9的有效载荷ts非常接近帧#6和#7的有效载荷,并且明显小于帧#8中接收到的确认的时间戳.

update-1:没有立即发送帧#9的事实可以通过TCP信道的慢启动来解释.实际上,一旦连接运行几分钟,问题也会出现,所以慢启动似乎不是一般的解释.

  1. 20:53:26.017415 IP 172.17.60.9.39943 > 172.17.152.124.56001: Flags [S],seq 2473022771,win 5840,options [mss 1460,sackOK,TS val 4219180820 ecr 0,nop,wscale 8],length 0

  2. 20:53:26.017423 IP 172.17.152.124.56001 > 172.17.60.9.39943: Flags [S.],seq 2948065596,ack 2473022772,win 5792,TS val 186598852 ecr 219180820,wscale 9],length 0

  3. 20:53:26.091940 IP 172.17.60.9.39943 > 172.17.152.124.56001: Flags [.],ack 1,win 23,options [nop,TS val 4219180894 ecr 186598852],length 0

  4. 20:53:26.091958 IP 172.17.60.9.39943 > 172.17.152.124.56001: Flags [P.],seq 1:15,w in 23,TS val 4219180895 ecr 186598852],length 14

  5. 20:53:26.091964 IP 172.17.152.124.56001 > 172.17.60.9.39943: Flags [.],ack 15,win 12,TS val 186598927 ecr 4219180895],length 0

  6. 20:53:26.128298 IP 172.17.152.124.56001 > 172.17.60.9.39943: Flags [P.],seq 1:257,TS val 186598963 ecr 4219180895],length 256

  7. 20:53:26.128519 IP 172.17.152.124.56001 > 172.17.60.9.39943: Flags [P.],seq 257:385,length 128

  8. 20:53:26.202465 IP 172.17.60.9.39943 > 172.17.152.124.56001: Flags [.],ack 257,win 27,TS val 4219181005 ecr 186598963],length 0

  9. 20:53:26.202475 IP 172.17.152.124.56001 > 172.17.60.9.39943: Flags [.],seq 385:1833,TS val 186599037 ecr 4219181005],length 1448

  10. 20:53:26.202480 IP 172.17.152.124.56001 > 172.17.60.9.39943: Flags [P.],seq 1833:2305,length 472

如果这很重要,两端都是Linux RHEL5盒子,2.6.18内核和网卡都使用e1000e驱动程序.

更新3
/etc/sysctl.conf的内容

[jlafaye@localhost ~]$cat /etc/sysctl.conf | grep -v "^#" | grep -v "^$" 
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.ipv4.tcp_rmem = 65536 4194304 16777216
net.ipv4.tcp_wmem = 65536 4194304 16777216 
net.core.netdev_max_backlog = 10000 
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_mem = 262144 4194304 16777216
kernel.shmmax = 68719476736

解决方法

在进一步挖掘我的流量之后,我能够看到我的数据只不过是一系列小爆发,它们之间的空闲时间很短.

使用有用的工具ss,我能够检索连接的当前拥塞窗口大小(请参阅输出中的cwnd值):

[user@localhost ~]$/usr/sbin/ss -i -t -e | grep -A 1 56001

ESTAB 0 0 192.168.1.1:56001
192.168.2.1:45614 uid:1001 ino:6873875 sk:17cd4200ffff8804
ts sackscalable wscale:8,9 rto:277 rtt:74/1 ato:40 cwnd:36 send 5.6Mbps rcv_space:5792

我多次运行该工具,发现拥塞窗口大小定期重置为初始值(10毫秒,在我的Linux机器上).连接不断循环回到慢启动阶段.在慢启动期间,具有超过窗口大小的多个消息的突发被延迟,等待与突发的第一个分组相关的ack.

流量由一系列突发组成的事实可能解释了拥塞窗口大小的重置.

通过在空闲期后停用慢启动模式,我能够摆脱延迟.

[user@host ~]$cat /proc/sys/net/ipv4/tcp_slow_start_after_idle 0

猜你在找的Linux相关文章