Débit TCP inférieur du serveur 1 Gbit / s au serveur 100 Mbit / s sur un RTT volumineux

9

Nous avons des infrastructures distribuées dans quelques sites majeurs à travers le monde - Singapour, Londres et Los Angeles. Le RTT entre deux emplacements quelconques est supérieur à 150 ms.

Nous avons récemment mis à niveau tous les serveurs pour utiliser des liaisons 1 Gbit / s (à partir de 100 Mbit / s). Nous avons effectué des tests basés sur TCP entre des serveurs aux différents emplacements et avons vu des résultats surprenants. Ces résultats sont entièrement reproductibles.

  1. Los Angeles (100 Mbps) à Londres (100 Mbps): ~ 96 Mbps de débit
  2. Los Angeles (100Mbps) à Londres (1Gbps): ~ 96Mbps de débit
  3. Los Angeles (1Gbps) à Londres (100Mbps): 10-40Mbps de débit (volatile)
  4. Los Angeles (1 Gbit / s) à Londres (1 Gbit / s): débit 10-40 Mbit / s (volatile)
  5. Los Angeles (1Gbps) à Los Angeles (1Gbps):> 900Mbps de débit

Il semble que chaque fois que l'expéditeur fonctionne à 1 Gbit / s, notre débit souffre de manière très significative sur les liaisons longues.

L'approche de test plus tôt est extrêmement simple - j'utilise simplement cURL pour télécharger un binaire de 1 Go depuis le serveur cible (donc dans le cas ci-dessus, le client cURL s'exécute sur le serveur de Londres et télécharge depuis LA, de sorte que LA est l'expéditeur) . Il s'agit bien sûr d'une seule connexion TCP.

En répétant les mêmes tests sur UDP en utilisant iperf, le problème disparaît!

  1. Los Angeles (100 Mbps) à Londres (100 Mbps): ~ 96 Mbps de débit
  2. Los Angeles (100Mbps) à Londres (1Gbps): ~ 96Mbps de débit
  3. Los Angeles (1 Gbps) à Londres (100 Mbps): ~ 96 Mbps de débit
  4. Los Angeles (1 Gbps) à Londres (1 Gbps):> 250 Mbps de débit

Cela pointe carrément vers un problème de configuration TCP ou NIC / port à mes yeux.

Les deux serveurs exécutent CentOS 6.x, avec TCP cubic. Les deux ont des fenêtres d'envoi et de réception TCP maximales de 8 Mo, et les horodatages TCP et les accusés de réception sélectifs sont activés. La même configuration TCP est utilisée dans tous les cas de test. La configuration TCP complète est ci-dessous:

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

Vous trouverez ci-joint quelques images de graphiques IO Wireshark de certains cas de test (désolé, je ne peux pas encore publier d'images directement):

Cas de test 1 (100Mbps -> 100Mbps) - beau transfert fluide. Aucune perte de capture. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png

Cas de test 3 (1Gbps -> 100Mbps) - le transfert votaile, prend beaucoup de temps pour arriver à n'importe quelle vitesse - n'approche jamais 100Mbps. Pourtant pas de pertes / retransmissions dans la capture! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png

Donc, en résumé, quand un lien long est utilisé avec une connexion à 1 Gbit / s, nous obtenons un débit TCP beaucoup plus faible que lorsque nous utilisons une connexion à 100 Mbit / s.

J'apprécierais beaucoup certains pointeurs de tous les experts TCP!

Merci!

MISE À JOUR (29/05/2013):

Nous avons résolu le problème avec le cas de test n ° 4 ci-dessus (émetteur 1 Gbit / s, récepteur 1 Gbit / s, sur un grand RTT). Nous pouvons maintenant atteindre ~ 970 Mbps en quelques secondes après le début du transfert. Le problème semble avoir été un commutateur utilisé avec le fournisseur d'hébergement. Le passage à un autre a résolu cela.

Cependant, le cas de test n ° 3 reste généralement problématique. Si nous avons un récepteur fonctionnant à 100 Mbit / s et l'expéditeur à 1 Gbit / s, alors nous voyons environ 2 à 3 minutes d'attente pour que le récepteur atteigne 100 Mbit / s (mais il atteint maintenant le plein débit, contrairement à avant). Dès que nous déposons l'expéditeur à 100 Mbps ou augmentons le récepteur à 1 Gbps, le problème disparaît et nous pouvons accélérer à pleine vitesse en une seconde ou deux.

La raison sous-jacente est que nous constatons des pertes, bien sûr, très peu de temps après le début du transfert. Cependant, cela ne correspond pas à ma compréhension du fonctionnement du démarrage lent; la vitesse de l'interface ne devrait pas avoir d'incidence sur cela, car elle devrait être régie par les ACK du récepteur.

Merci de bien vouloir nous faire part de vos suggestions! Si je pouvais offrir une prime ici, je le ferais!

Sam
la source
1
Utilisez-vous le déchargement TCP sur la carte réseau de chaque côté? Votre utilisation du déchargement TCP varie-t-elle du 100M au NIC 1G? Si cela est utilisé dans l'un des cas de test, il peut être utile de répéter les tests avec celui désactivé juste pour voir si le moteur de déchargement TCP sur la carte réseau 100M peut entraver le fonctionnement de la communication 1G (ce commentaire est intentionnellement main-ondulée juste pour élever généralement la TOE)
FliesLikeABrick
Bonne question! Le déchargement de segmentation TCP est désactivé aux deux extrémités. Le déchargement de segmentation générique est activé aux deux extrémités. Je l'ai également répété avec TSO activé, et cela n'a fait aucune différence notable.
Sam
Essayez de désactiver le déchargement de segmentation générique, au moins du côté 100M, et répétez vos tests
FliesLikeABrick
Merci pour la suggestion, mais pas de joie - mêmes résultats avec gso activé ou désactivé des deux côtés.
Sam
1 Gbit / s à 150 ms + donne un produit de délai de bande passante très important, supérieur à 18 Mo. Que se passe-t-il si vous augmentez vos tampons de socket? tcp_*mem = 4096 1048576 33554432Vous n'avez pas activé les trames Jumbo sur les liens 1 Gbit / s, n'est-ce pas? Cela pourrait causer une fragmentation des frais généraux quelque part.
suprjami

Réponses:

1

Le problème principal est le grand retard du WAN. Ce sera bien pire s'il a également perdu un paquet aléatoire.

1, le tcp_mem doit également définir un grand pour allouer plus de mémoire. Par exemple, définissez-le comme net.ipv4.tcp_mem = 4643328 6191104 9286656

2, vous pouvez capturer les paquets via wirehark / tcpdump pendant environ plusieurs minutes, puis analyser s'il a perdu des paquets aléatoires. Vous pouvez également télécharger le fichier de paquets si vous le souhaitez.

3, vous pouvez essayer de régler les autres paramètres TCP par exemple. définissez tcp_westwood = 1 et tcp_bic = 1

HarryREN
la source
Merci, mais nous avons essayé tout cela. Le délai WAN n'est pas le problème - nous pouvons atteindre 100 Mbps presque immédiatement si nous utilisons des ports à 100 Mbps, mais dès que l'on passe à 1 Gbps, nous portons un toast.
Sam
1

Résolu! Pour plus de détails, voir http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813

En bref, il semble que le serveur connecté à 1 Gbit / s enverrait des rafales de trafic pendant la phase de croissance exponentielle de TCP qui inonderaient les tampons dans un périphérique intermédiaire (qui sait quoi). Cela laisse deux options:

1) Contactez chaque opérateur de réseau intermédiaire et demandez-lui de configurer les tampons appropriés pour autoriser la bande passante et la RTT souhaitées. Assez peu probable! 2) Limitez les rafales.

J'ai choisi de limiter chaque flux TCP pour fonctionner à 100 Mbps au maximum. Le nombre ici est assez arbitraire - j'ai choisi 100 Mbps uniquement parce que je savais que le chemin précédent pouvait gérer 100 Mbps et je n'en avais plus besoin pour un flux individuel .

J'espère que cela aidera quelqu'un à l'avenir.

Sam
la source
0

En répétant les mêmes tests sur UDP en utilisant iperf, le problème disparaît!

Los Angeles (1 Gbps) à Londres (1 Gbps):> 250 Mbps de débit

Le problème ne semble pas avoir disparu, environ 75% de vos paquets sont abandonnés? Si TCP se met tout le temps à démarrer lentement, votre bande passante moyenne peut être plutôt faible.

Btw, avez-vous des repères pour Londres à LA et Londres à Londres?

Jens Timmerman
la source
J'ai oublié de mentionner que le client est lent ... Si nous répétons avec deux clients rapides, nous atteignons ~ 970 Mbps dans les deux sens.
Sam