我们的基础设施分布在全球几个主要地区-新加坡,伦敦和洛杉矶。任何两个位置之间的RTT均超过150ms。
我们最近将所有服务器升级为使用1Gbps链接(从100Mbps开始)。我们已经在不同位置的服务器之间运行了一些基于TCP的测试,并且看到了一些令人惊讶的结果。这些结果是完全可重复的。
- 洛杉矶(100Mbps)到伦敦(100Mbps):〜96Mbps吞吐量
- 洛杉矶(100Mbps)至伦敦(1Gbps):〜96Mbps吞吐量
- 洛杉矶(1Gbps)至伦敦(100Mbps):10-40Mbps吞吐量(易失)
- 洛杉矶(1Gbps)至伦敦(1Gbps):10-40Mbps吞吐量(易失)
- 洛杉矶(1Gbps)至洛杉矶(1Gbps):吞吐量> 900Mbps
看起来,只要发件人以1Gbps的速度运行,在长链路上,我们的吞吐量就会受到极大影响。
先前的测试方法非常简单-我只是使用cURL从目标服务器下载1GB二进制文件(因此,在上述情况下,cURL客户端在London服务器上运行并从LA下载,因此LA是发送者) 。当然,这是使用单个TCP连接。
使用iperf在UDP上重复相同的测试,问题消失了!
- 洛杉矶(100Mbps)到伦敦(100Mbps):〜96Mbps吞吐量
- 洛杉矶(100Mbps)至伦敦(1Gbps):〜96Mbps吞吐量
- 洛杉矶(1Gbps)至伦敦(100Mbps):〜96Mbps吞吐量
- 洛杉矶(1Gbps)至伦敦(1Gbps):吞吐量> 250Mbps
这直指我眼中的某些TCP或NIC /端口配置问题。
两台服务器都运行带有TCP三次的CentOS6.x。两者都具有最大8MB的TCP发送和接收窗口,并启用了TCP时间戳和选择性确认。所有测试用例都使用相同的TCP配置。完整的TCP配置如下:
net.core.somaxconn = 128
net.core.xfrm_aevent_etime = 10
net.core.xfrm_aevent_rseqth = 2
net.core.xfrm_larval_drop = 1
net.core.xfrm_acq_expires = 30
net.core.wmem_max = 8388608
net.core.rmem_max = 8388608
net.core.wmem_default = 131072
net.core.rmem_default = 131072
net.core.dev_weight = 64
net.core.netdev_max_backlog = 1000
net.core.message_cost = 5
net.core.message_burst = 10
net.core.optmem_max = 20480
net.core.rps_sock_flow_entries = 0
net.core.netdev_budget = 300
net.core.warnings = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_retrans_collapse = 1
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_fin_timeout = 60
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_stdurg = 0
net.ipv4.tcp_rfc1337 = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_fack = 1
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_mem = 1528512 2038016 3057024
net.ipv4.tcp_wmem = 4096 131072 8388608
net.ipv4.tcp_rmem = 4096 131072 8388608
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_frto = 2
net.ipv4.tcp_frto_response = 0
net.ipv4.tcp_low_latency = 0
net.ipv4.tcp_no_metrics_save = 0
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_tso_win_divisor = 3
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_abc = 0
net.ipv4.tcp_mtu_probing = 0
net.ipv4.tcp_base_mss = 512
net.ipv4.tcp_workaround_signed_windows = 0
net.ipv4.tcp_dma_copybreak = 4096
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_max_ssthresh = 0
net.ipv4.tcp_thin_linear_timeouts = 0
net.ipv4.tcp_thin_dupack = 0
附带的是一些测试用例的wireshark IO图的几个图像(对不起,我还不能直接发布图像):
测试案例1(100Mbps-> 100Mbps) -流畅的传输。没有损失。- http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png
测试案例3( 1Gbps- > 100Mbps) -可变传输,需要很长时间才能达到任何速度-永远不会接近100Mbps。捕获中没有丢失/转发!- http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png
因此,总而言之,当长链接与1Gbps连接一起使用时,与使用100Mbps连接时相比,我们获得的TCP吞吐量要低得多。
非常感谢任何TCP专家的指导!
谢谢!
更新(2013-05-29):
我们已经通过上面的测试案例4(在大型RTT上发送1Gbps,接收1Gbps的接收器)解决了该问题。现在,我们可以在传输开始后的几秒钟内达到970Mbps。该问题似乎是与托管服务提供商一起使用的一个开关。转向另一种解决了这一问题。
但是,第3个测试案例仍然存在问题。如果我们有一个接收器以100Mbps的速度运行而发送器以1Gbps的速度运行,那么我们将等待大约2-3分钟的时间来等待接收器达到100Mbps(但与以前不同,它现在已经达到了全速率)。一旦将发送器的速度降低到100Mbps或将接收器的速度提高到1Gbps,问题就消失了,我们可以在一两秒钟内将速度提升到全速。
根本原因是,在转移开始后不久,我们当然会看到损失。但是,这与我对慢启动的工作原理的理解并不一致。接口速度对此没有任何影响,因为它应该由接收器的ACK来控制。
建议感激地收到!如果我可以在这里提供赏金,我会的!
tcp_*mem = 4096 1048576 33554432
您尚未在1Gbps链路上启用巨型帧吗?这可能会导致某个地方的碎片开销。