我一直尝试应用在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 机器上不起作用。
第二种设置至少有两个重要的区别:
- 在我失败的实验中,Linux 机器是虚拟机,而在我成功的实验中,Linux 机器在裸机上运行。
- 在我失败的实验中,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 调优,肯定必须有近总是我认为它是端点之间的路由器?)。
或者,也许我的两个实验之间存在一些其他差异,这是导致第一种情况下吞吐量可怕的原因(但那可能是什么呢?)