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.
- Los Angeles (100 Mbps) à Londres (100 Mbps): ~ 96 Mbps de débit
- Los Angeles (100Mbps) à Londres (1Gbps): ~ 96Mbps de débit
- Los Angeles (1Gbps) à Londres (100Mbps): 10-40Mbps de débit (volatile)
- Los Angeles (1 Gbit / s) à Londres (1 Gbit / s): débit 10-40 Mbit / s (volatile)
- 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!
- Los Angeles (100 Mbps) à Londres (100 Mbps): ~ 96 Mbps de débit
- Los Angeles (100Mbps) à Londres (1Gbps): ~ 96Mbps de débit
- Los Angeles (1 Gbps) à Londres (100 Mbps): ~ 96 Mbps de débit
- 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!
tcp_*mem = 4096 1048576 33554432
Vous 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.