Niedrigerer TCP-Durchsatz vom 1-Gbit / s-Server als vom 100-Mbit / s-Server über große RTT


9

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.

  1. Los Angeles (100 Mbit / s) nach London (100 Mbit / s): ~ 96 Mbit / s Durchsatz
  2. Los Angeles (100 Mbit / s) nach London (1 Gbit / s): ~ 96 Mbit / s Durchsatz
  3. Los Angeles (1 Gbit / s) nach London (100 Mbit / s): 10-40 Mbit / s Durchsatz (flüchtig)
  4. Los Angeles (1 Gbit / s) nach London (1 Gbit / s): 10-40 Mbit / s Durchsatz (flüchtig)
  5. 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!

  1. Los Angeles (100 Mbit / s) nach London (100 Mbit / s): ~ 96 Mbit / s Durchsatz
  2. Los Angeles (100 Mbit / s) nach London (1 Gbit / s): ~ 96 Mbit / s Durchsatz
  3. Los Angeles (1 Gbit / s) nach London (100 Mbit / s): ~ 96 Mbit / s Durchsatz
  4. 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!


1
Verwenden Sie TCP-Offload auf der Netzwerkkarte auf beiden Seiten? Variiert Ihre Verwendung von TCP-Offload von 100M bis 1G-NIC? Wenn dies in einem der Testfälle verwendet wird, kann es sich lohnen, die Tests mit deaktiviertem Test zu wiederholen, um festzustellen, ob die TCP-Offload-Engine auf der 100M-Netzwerkkarte die Leistung der 1G-Kommunikation beeinträchtigt (dieser Kommentar ist absichtlich Hand-Wavey, nur um generell TOE zu
erziehen

Gute Frage! Das Auslagern der TCP-Segmentierung ist an beiden Enden deaktiviert. Das generische Segmentierungs-Offload ist an beiden Enden aktiviert. Ich habe es auch mit aktiviertem TSO wiederholt, und es machte keinen merklichen Unterschied.
Sam

Versuchen Sie, das generische Segmentierungs-Offload zumindest auf der 100-
Millionen-

Danke für den Vorschlag, aber keine Freude - gleiche Ergebnisse mit gso auf beiden Seiten ein- oder ausschalten.
Sam

1 Gbit / s bei 150 ms + ergibt ein sehr großes Produkt mit Bandbreitenverzögerung von über 18 MB. Was passiert, wenn Sie Ihre Socket-Puffer hochfahren? tcp_*mem = 4096 1048576 33554432Sie haben Jumbo Frames für die 1-Gbit / s-Links nicht aktiviert, oder? Das könnte irgendwo zu Fragmentierungskosten führen.
Suprjami

Antworten:


1

Das Hauptproblem ist die große WAN-Verzögerung. Es wird sehr schlimmer sein, wenn auch ein zufälliges Paket verloren geht.

In 1 muss das tcp_mem auch groß gesetzt werden, um mehr Speicher zuzuweisen. Legen Sie es beispielsweise als net.ipv4.tcp_mem = 4643328 6191104 9286656 fest

2, können Sie die Pakete über wireshark / tcpdump für einige Minuten erfassen und dann analysieren, ob zufällige Pakete verloren gegangen sind. Sie können die Paketdatei auch hochladen, wenn Sie möchten.

3 können Sie versuchen, die anderen TCP-Parameter z. setze tcp_westwood = 1 und tcp_bic = 1


Danke, aber wir haben alle ausprobiert. Die WAN-Verzögerung ist nicht das Problem - wir können fast sofort 100 Mbit / s erreichen, wenn wir 100 Mbit / s-Ports verwenden, aber sobald einer auf 1 Gbit / s wechselt, stoßen wir an.
Sam

1

Gelöst! Ausführliche Informationen finden Sie unter http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813

Kurz gesagt, es scheint, dass der mit 1 Gbit / s verbundene Server während der exponentiellen Wachstumsphase von TCP Verkehrsstöße senden würde, die Puffer in einem Zwischengerät überfluten würden (wer weiß was). Dies lässt zwei Möglichkeiten:

1) Wenden Sie sich an jeden zwischengeschalteten Netzbetreiber und lassen Sie ihn geeignete Puffer konfigurieren, um meine gewünschte Bandbreite und RTT zu berücksichtigen. Ziemlich unwahrscheinlich! 2) Begrenzen Sie die Bursts.

Ich habe mich dafür entschieden, jeden TCP-Fluss auf maximal 100 Mbit / s zu beschränken. Die Anzahl hier ist ziemlich willkürlich - ich habe 100 Mbit / s gewählt, nur weil ich wusste, dass der vorherige Pfad 100 Mbit / s verarbeiten kann und ich für einen einzelnen Flow keine weiteren mehr benötige .

Hoffe das hilft jemandem in der Zukunft.


0

Wenn Sie dieselben Tests über UDP mit iperf wiederholen, verschwindet das Problem!

Los Angeles (1 Gbit / s) nach London (1 Gbit / s):> 250 Mbit / s Durchsatz

Das Problem scheint nicht verschwunden zu sein, ungefähr 75% Ihrer Pakete werden verworfen? Wenn TCP ständig langsam startet, ist Ihre durchschnittliche Bandbreite möglicherweise eher gering.

Übrigens, haben Sie Benchmarks für London nach LA und London nach London?


Ich habe vergessen zu erwähnen, dass der Client langsam ist ... Wenn wir mit zwei schnellen Clients wiederholen, erreichen wir bidirektional ~ 970 Mbit / s.
Sam
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.