Wir haben die Infrastruktur an einigen wichtigen Standorten auf der ganzen Welt verteilt - in Singapur, London und Los Angeles. Die RTT zwischen zwei beliebigen Standorten liegt über> 150 ms.
Wir haben kürzlich alle Server auf 1-Gbit / s-Verbindungen (von 100 Mbit / s) aktualisiert. Wir haben einige TCP-basierte Tests zwischen Servern an den verschiedenen Standorten durchgeführt und einige überraschende Ergebnisse erzielt. Diese Ergebnisse sind vollständig wiederholbar.
- Los Angeles (100 Mbit / s) nach London (100 Mbit / s): ~ 96 Mbit / s Durchsatz
- Los Angeles (100 Mbit / s) nach London (1 Gbit / s): ~ 96 Mbit / s Durchsatz
- Los Angeles (1 Gbit / s) nach London (100 Mbit / s): 10-40 Mbit / s Durchsatz (flüchtig)
- Los Angeles (1 Gbit / s) nach London (1 Gbit / s): 10-40 Mbit / s Durchsatz (flüchtig)
- Los Angeles (1 Gbit / s) nach Los Angeles (1 Gbit / s):> 900 Mbit / s Durchsatz
Es scheint, dass unser Durchsatz bei langen Verbindungen sehr stark leidet, wenn der Absender mit 1 Gbit / s läuft.
Der frühere Testansatz ist äußerst einfach: Ich verwende nur cURL, um eine 1-GB-Binärdatei vom Zielserver herunterzuladen (im obigen Fall wird der cURL-Client auf dem Londoner Server ausgeführt und von LA heruntergeladen, sodass LA der Absender ist). . Dies verwendet natürlich eine einzelne TCP-Verbindung.
Wenn Sie dieselben Tests über UDP mit iperf wiederholen, verschwindet das Problem!
- Los Angeles (100 Mbit / s) nach London (100 Mbit / s): ~ 96 Mbit / s Durchsatz
- Los Angeles (100 Mbit / s) nach London (1 Gbit / s): ~ 96 Mbit / s Durchsatz
- Los Angeles (1 Gbit / s) nach London (100 Mbit / s): ~ 96 Mbit / s Durchsatz
- Los Angeles (1 Gbit / s) nach London (1 Gbit / s):> 250 Mbit / s Durchsatz
Dies deutet in meinen Augen direkt auf ein Problem mit der TCP- oder NIC / Port-Konfiguration hin.
Auf beiden Servern wird CentOS 6.x mit TCP Cubic ausgeführt. Beide haben maximal 8 MB TCP-Sende- und Empfangsfenster sowie aktivierte TCP-Zeitstempel und selektive Bestätigungen. In allen Testfällen wird dieselbe TCP-Konfiguration verwendet. Die vollständige TCP-Konfiguration finden Sie unten:
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
Im Anhang finden Sie einige Bilder von Wireshark-E / A-Diagrammen einiger Testfälle (leider kann ich noch keine Bilder direkt veröffentlichen):
Testfall 1 (100 Mbit / s -> 100 Mbit / s) - schöne reibungslose Übertragung. Keine Verluste bei der Erfassung. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png
Testfall 3 (1 Gbit / s -> 100 Mbit / s) - Votaile-Übertragung, es dauert lange, bis eine Geschwindigkeit erreicht ist - nähert sich niemals 100 Mbit / s. Noch keine Verluste / Neuübertragungen bei der Erfassung! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png
Zusammenfassend lässt sich sagen, dass bei Verwendung einer langen Verbindung mit einer 1-Gbit / s-Verbindung ein viel geringerer TCP-Durchsatz erzielt wird als bei Verwendung einer 100-Mbit / s-Verbindung.
Ich würde mich sehr über einige Hinweise von TCP-Experten freuen!
Vielen Dank!
UPDATE (29.05.2013):
Wir haben das Problem mit Testfall Nr. 4 oben gelöst (1-Gbit / s-Sender, 1-Gbit / s-Empfänger über eine große RTT). Wir können jetzt innerhalb weniger Sekunden nach Beginn der Übertragung ~ 970 Mbit / s erreichen. Das Problem scheint ein Switch gewesen zu sein, der vom Hosting-Anbieter verwendet wurde. Der Wechsel zu einem anderen hat das gelöst.
Testfall Nr. 3 bleibt jedoch meist problematisch. Wenn wir einen Empfänger mit 100 Mbit / s und einen Absender mit 1 Gbit / s haben, sehen wir ungefähr 2-3 Minuten Wartezeit, bis der Empfänger 100 Mbit / s erreicht (aber im Gegensatz zu zuvor erreicht er jetzt die volle Rate). Sobald wir den Sender auf 100 Mbit / s senken oder den Empfänger auf 1 Gbit / s erhöhen, verschwindet das Problem und wir können in ein oder zwei Sekunden auf volle Geschwindigkeit hochfahren.
Der Grund dafür ist, dass wir natürlich sehr bald nach Beginn der Übertragung Verluste sehen. Dies stimmt jedoch nicht mit meinem Verständnis der Funktionsweise von Slow-Start überein. Die Schnittstellengeschwindigkeit sollte keinen Einfluss darauf haben, da sie von den ACKs des Empfängers gesteuert werden sollte.
Vorschläge dankbar erhalten bitte! Wenn ich hier ein Kopfgeld anbieten könnte, würde ich!
tcp_*mem = 4096 1048576 33554432
Sie haben Jumbo Frames für die 1-Gbit / s-Links nicht aktiviert, oder? Das könnte irgendwo zu Fragmentierungskosten führen.