有时无法调整 Linux TCP 堆栈以改善高延迟性能

有时无法调整 Linux TCP 堆栈以改善高延迟性能

我一直尝试应用在http://fasterdata.es.net/host-tuning/

当您阅读整个问题时您会发现,有时 es.net 调整指南对我有效,有时则无效,而且我还无法弄清楚区别因素是什么。

我已经建立了一个基准实验室环境,内容如下:

  • 一台运行 Ubuntu 14.04 的 Linux 机器
  • 一台运行 10.6.8 的 Mac OS X 机器

这两台机器通过高速、高带宽的内部网络连接,我将其用于测试目的。

我目前用于分析的主要工具是 iperf、pchar、tcpdump 和 Wireshark。

首先,我在 Mac 上运行“iperf -s”,在 Linux 机器上运行“iperf -c”,我可靠且可重复地获得了约 940 Mbps 的测量带宽,这对我来说很有意义,因为我相信我的机器是通过 1 Gbps 网络连接的。

我用“pchar”确认这些测量值。

然后我人为地在这个连接中引入高延迟,通过执行以下操作:

tc qdisc add dev eth0 root netem delay 78ms

当我这样做时,iperf 和 pchar 都会报告带宽下降到大约 75-100 Mbps 的范围。

有趣的是,这些数字也经常出现波动。但它们都很糟糕。

我认为这与此处描述的问题相符:http://fasterdata.es.net/host-tuning/background/因此我希望观察到我可以通过调整两台机器上的 TCP 堆栈来(某种程度上)解决这个问题。

在 Mac 上,我使用 'sysctl -w' 来设置

net.inet.tcp.win_scale_factor=8
kern.ipc.maxsockbuf=4194304
net.inet.tcp.recvspace=2097152

尝试将 kern.ipc.maxsockbuf 设置为更高的值会被操作系统拒绝,因为“结果太大”。这可能是此版本的 Mac OS X 的限制,如下所述:https://discussions.apple.com/thread/2581395(我还没有尝试过这里描述的解决此限制的复杂方法:https://www.myricom.com/software/myri10ge/391-how-can-i-restore-the-socket-buffer-sizes-in-macosx-10-6.html

同时,在 Linux 机器上,我使用 'sysctl -w' 来设置

net.core.wmem_max=16777216
net.ipv4.tcp_wmem = 4096 8388608 16777216
net.core.rmem_max=16777216
net.ipv4.tcp_rmem = 4096 8388608 16777216

然而,这些调整似乎都无法改变 iperf 报告的数字。

在所有这些调整生效之后,iperf 仍然报告测量的带宽约为 90 Mbps,据我所知,与进行调整之前的值相比没有变化。

我已经使用 tcpdump 捕获了此配置的数据包跟踪,并使用 Wireshark 查看了它们,据我所知,从 Mac 流回 Linux 机器的 ACK 消息表明窗口大小接近 4MB。

然而,数据包跟踪似乎告诉我,Linux 机器不愿意一次发送超过 32K 的未确认数据,并且“飞行中的字节数”从未超过这个数字。

数据包跟踪没有显示任何丢失数据包的证据,例如重新传输消息;但是,它们有时会显示一些数据包重新排序的证据。

我做错了什么?为什么 TCP 调优技术描述在http://fasterdata.es.net/host-tuning/对我来说不起作用?

更新:

我在一次此类运行的 tcpdump 数据包跟踪上使用了“tcptrace -lW”,结果显示如下。

TCP connection 3:
    host e:        *****:55706
    host f:        *****:5001
    complete conn: yes
    first packet:  Tue Sep  8 07:48:35.569180 2015
    last packet:   Tue Sep  8 07:48:55.823746 2015
    elapsed time:  0:00:20.254566
    total packets: 112524
    filename:      sample.pcap
   e->f:                  f->e:
     total packets:         91306           total packets:         21218      
     ack pkts sent:         91305           ack pkts sent:         21218      
     pure acks sent:            2           pure acks sent:        21216      
     sack pkts sent:            0           sack pkts sent:          820      
     dsack pkts sent:           0           dsack pkts sent:           0      
     max sack blks/ack:         0           max sack blks/ack:         3      
     unique bytes sent: 131989528           unique bytes sent:         0      
     actual data pkts:      91303           actual data pkts:          0      
     actual data bytes: 132057584           actual data bytes:         0      
     rexmt data pkts:          47           rexmt data pkts:           0      
     rexmt data bytes:      68056           rexmt data bytes:          0      
     zwnd probe pkts:           0           zwnd probe pkts:           0      
     zwnd probe bytes:          0           zwnd probe bytes:          0      
     outoforder pkts:           0           outoforder pkts:           0      
     pushed data pkts:        435           pushed data pkts:          0      
     SYN/FIN pkts sent:       1/1           SYN/FIN pkts sent:       1/1      
     req 1323 ws/ts:          Y/Y           req 1323 ws/ts:          Y/Y      
     adv wind scale:            9           adv wind scale:            6      
     req sack:                  Y           req sack:                  Y      
     sacks sent:                0           sacks sent:              820      
     urgent data pkts:          0 pkts      urgent data pkts:          0 pkts 
     urgent data bytes:         0 bytes     urgent data bytes:         0 bytes
     mss requested:          1460 bytes     mss requested:          1460 bytes
     max segm size:          1448 bytes     max segm size:             0 bytes
     min segm size:            24 bytes     min segm size:             0 bytes
     avg segm size:          1446 bytes     avg segm size:             0 bytes
     max win adv:           29696 bytes     max win adv:         3728256 bytes
     min win adv:           29696 bytes     min win adv:         3116992 bytes
     zero win adv:              0 times     zero win adv:              0 times
     avg win adv:           29696 bytes     avg win adv:         3725120 bytes
     max owin:             695209 bytes     max owin:                  1 bytes
     min non-zero owin:         1 bytes     min non-zero owin:         1 bytes
     avg owin:             129597 bytes     avg owin:                  1 bytes
     wavg owin:            186185 bytes     wavg owin:                 0 bytes
     initial window:        13056 bytes     initial window:            0 bytes
     initial window:           10 pkts      initial window:            0 pkts 
     ttl stream length: 131989528 bytes     ttl stream length:         0 bytes
     missed data:               0 bytes     missed data:               0 bytes
     truncated data:            0 bytes     truncated data:            0 bytes
     truncated packets:         0 pkts      truncated packets:         0 pkts 
     data xmit time:       20.095 secs      data xmit time:        0.000 secs 
     idletime max:           81.0 ms        idletime max:           79.8 ms   

我不明白为什么平均输出功率仍然这么小。

我觉得这与拥塞窗口有关,但我不明白为什么拥塞窗口会限制我的吞吐量。

我使用 Linux 的“ss”工具在运行期间观察了 cwnd,它确实显示 cwnd 没有增加:

State      Recv-Q Send-Q      Local Address:Port          Peer Address:Port   
ESTAB      0      696600        N.N.N.N:55708         N.N.N.N:5001    
     skmem:(r0,rb8388608,t482,tb2097152,f3584,w2097664,o0,bl0) cubic wscale:8,9 rto:280 rtt:80/3 mss:1448 cwnd:486 ssthresh:328 send 70.4Mbps unacked:482 retrans:0/89 rcv_space:29200
...

    ESTAB      0      626984        N.N.N.N:55708         N.N.N.N:5001    
     skmem:(r0,rb8388608,t243,tb2097152,f216832,w1884416,o0,bl0) cubic wscale:8,9 rto:280 rtt:80/3 mss:1448 cwnd:243 ssthresh:240 send 35.2Mbps unacked:243 retrans:0/231 rcv_space:29200
...
ESTAB      0      697936        N.N.N.N:55708         N.N.N.N:5001    
     skmem:(r0,rb8388608,t289,tb2097152,f3584,w2097664,o0,bl0) cubic wscale:8,9 rto:276 rtt:79.5/3 mss:1448 cwnd:290 ssthresh:240 send 42.3Mbps unacked:290 retrans:0/231 rcv_space:29200

这个“ss”输出中是否有任何线索可以解释为什么我的吞吐量如此低?

更新2

我获得了一些额外的硬件资源。

具体来说,我能够找到另一个 Linux 机器,并用它来测试我的 Mac。再次在 Linux 机器上,我通过执行以下操作模拟了高延迟连接:

tc qdisc add dev eth0 root netem delay 78ms

在这个盒子上,我再次按照http://fasterdata.es.net/host-tuning/设置变量

net.core.wmem_max=16777216
net.ipv4.tcp_wmem = 4096 8388608 16777216
net.core.rmem_max=16777216
net.ipv4.tcp_rmem = 4096 8388608 16777216

然后“iperf”报告两台机器之间测量的吞吐量为每秒 911 兆比特。

因此,我现在已经成功地将 TCP 调整技术应用到 Linux 机器上。

但是,我仍然感到困惑,为什么完全相同的技术在其他 Linux 机器上不起作用。

第二种设置至少有两个重要的区别:

  1. 在我失败的实验中,Linux 机器是虚拟机,而在我成功的实验中,Linux 机器在裸机上运行。
  2. 在我失败的实验中,Linux VM 和我的 Mac 位于不同的子网上,由路由器隔开,而在我成功的实验中,Linux 机器和我的 Mac 位于同一个子网上。

因此,也许http://fasterdata.es.net/host-tuning/如果正在调整的 Linux 机器是虚拟机,则不起作用,可能是因为 VM 中的 Linux 网络堆栈与裸机 Linux 机器上的 Linux 网络堆栈有很大不同,因此对相同的调整没有响应。

或者,也许在http://fasterdata.es.net/host-tuning/如果端点之间有路由器,则无法工作(尽管http://fasterdata.es.net/host-tuning/对于互联网规模的 WAN 调优,肯定必须有近总是我认为它是端点之间的路由器?)。

或者,也许我的两个实验之间存在一些其他差异,这是导致第一种情况下吞吐量可怕的原因(但那可能是什么呢?)

相关内容