Scénario : Nous avons un certain nombre de clients Windows qui téléchargent régulièrement de gros fichiers (FTP/SVN/HTTP PUT/SCP) vers des serveurs Linux distants de ~100-160ms. Nous disposons d'une bande passante synchrone de 1Gbit/s au bureau et les serveurs sont soit des instances AWS, soit physiquement hébergés dans des centres de données américains.
Le rapport initial indiquait que les téléchargements vers une nouvelle instance de serveur étaient beaucoup plus lents qu'ils ne pouvaient l'être. Cela s'est confirmé lors des tests et à partir de plusieurs sites ; les clients ont constaté un débit stable de 2 à 5 Mbit/s vers l'hôte à partir de leurs systèmes Windows.
J'ai éclaté iperf -s
sur une instance AWS, puis à partir d'une instance Fenêtres client dans le bureau :
iperf -c 1.2.3.4
[ 5] local 10.169.40.14 port 5001 connected with 1.2.3.4 port 55185
[ 5] 0.0-10.0 sec 6.55 MBytes 5.48 Mbits/sec
iperf -w1M -c 1.2.3.4
[ 4] local 10.169.40.14 port 5001 connected with 1.2.3.4 port 55239
[ 4] 0.0-18.3 sec 196 MBytes 89.6 Mbits/sec
Ce dernier chiffre peut varier de manière significative lors de tests ultérieurs, (Vagaries of AWS) mais se situe généralement entre 70 et 130Mbit/s, ce qui est plus que suffisant pour nos besoins. En faisant un Wiresharking de la session, je peux voir :
-
iperf -c
Windows SYN - Window 64kb, Scale 1 - Linux SYN, ACK : Window 14kb, Scale : 9 (*512) -
iperf -c -w1M
Windows SYN - Windows 64kb, échelle 1 - Linux SYN, ACK : Window 14kb, échelle : 9
Il est clair que la liaison peut supporter ce débit élevé, mais je dois explicitement définir la taille de la fenêtre pour l'utiliser, ce que la plupart des applications réelles ne me permettent pas de faire. Les poignées de main TCP utilisent les mêmes points de départ dans les deux cas, mais la poignée forcée s'échelonne
Inversement, à partir d'un client Linux sur le même réseau, une ligne droite, iperf -c
(en utilisant la valeur par défaut du système, soit 85kb) :
[ 5] local 10.169.40.14 port 5001 connected with 1.2.3.4 port 33263
[ 5] 0.0-10.8 sec 142 MBytes 110 Mbits/sec
Sans aucun forçage, il évolue comme prévu. Cela ne peut pas être quelque chose dans les sauts intermédiaires ou nos commutateurs/routeurs locaux et semble affecter les clients Windows 7 et 8 de la même manière. J'ai lu beaucoup de guides sur l'auto-tuning, mais il s'agit généralement de désactiver complètement la mise à l'échelle pour contourner un mauvais kit de mise en réseau domestique.
Quelqu'un peut-il me dire ce qui se passe ici et me donner un moyen d'y remédier ? (De préférence quelque chose que je peux coller dans le registre via GPO).
Notes
L'instance AWS Linux en question a les paramètres de noyau suivants appliqués dans sysctl.conf
:
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.ipv4.tcp_rmem = 4096 1048576 16777216
net.ipv4.tcp_wmem = 4096 1048576 16777216
J'ai utilisé dd if=/dev/zero | nc
redirigeant vers /dev/null
au niveau du serveur pour exclure les iperf
et de supprimer tout autre goulot d'étranglement éventuel, mais les résultats sont sensiblement les mêmes. Les tests avec ncftp
(Cygwin, Native Windows, Linux) se déroulent de la même manière que les tests iperf ci-dessus sur leurs plates-formes respectives.
Editer
J'ai repéré un autre élément cohérent qui pourrait être pertinent :
Voici la première seconde de la capture de 1 Mo, avec un zoom avant. On peut y voir Démarrage lent en action lorsque la fenêtre s'agrandit et que la mémoire tampon s'agrandit. Il y a ensuite ce petit plateau de ~0,2s exactement au moment où la fenêtre par défaut iperf test s'aplatit pour toujours. Celui-ci s'étend bien sûr à des hauteurs beaucoup plus vertigineuses, mais il est curieux qu'il y ait une pause dans la mise à l'échelle (les valeurs sont de 1022 octets * 512 = 523264) avant qu'il ne le fasse.
Mise à jour - 30 juin.
Suivi des différentes réponses :
- Activation de CTCP - Cela ne fait aucune différence ; la mise à l'échelle des fenêtres est identique. (Si je comprends bien, ce paramètre augmente la vitesse à laquelle la fenêtre de congestion est agrandie plutôt que la taille maximale qu'elle peut atteindre).
- Activation des horodatages TCP. - Pas de changement ici non plus.
- Algorithme de Nagle - C'est logique et, au moins, cela signifie que je peux probablement ignorer ces points particuliers dans le graphique en tant qu'indication du problème.
- fichiers pcap : Fichier zip disponible ici : https://www.dropbox.com/s/104qdysmk01lnf6/iperf-pcaps-10s-Win%2BLinux-2014-06-30.zip (Anonymisé avec bittwiste, extrait à ~150MB car il y en a un de chaque client OS pour comparaison)
Mise à jour 2 - 30 juin
O, suite à la suggestion de Kyle, j'ai activé ctcp et désactivé le délestage de cheminée : Paramètres globaux TCP
----------------------------------------------
Receive-Side Scaling State : enabled
Chimney Offload State : disabled
NetDMA State : enabled
Direct Cache Acess (DCA) : disabled
Receive Window Auto-Tuning Level : normal
Add-On Congestion Control Provider : ctcp
ECN Capability : disabled
RFC 1323 Timestamps : enabled
Initial RTO : 3000
Non Sack Rtt Resiliency : disabled
Malheureusement, le débit n'a pas changé.
J'ai cependant une question de cause à effet : Les graphiques représentent la valeur RWIN définie dans les ACK du serveur au client. Avec les clients Windows, ai-je raison de penser que Linux ne met pas cette valeur à l'échelle au-delà de ce point bas parce que le CWIN limité du client empêche même ce tampon d'être rempli ? Pourrait-il y avoir une autre raison pour laquelle Linux limite artificiellement le RWIN ?
Note : J'ai essayé d'activer l'ECN pour le plaisir, mais cela n'a rien changé.
Mise à jour 3 - 31 juin.
Aucun changement après la désactivation de l'heuristique et de l'autotuning RWIN. J'ai mis à jour les pilotes réseau Intel à la dernière version (12.10.28.0) avec un logiciel qui expose les réglages de fonctionnalité via les onglets du gestionnaire de périphériques. La carte est une carte réseau embarquée 82579V - (je vais faire d'autres tests avec des clients qui utilisent Realtek ou d'autres fournisseurs).
En me concentrant sur la carte d'interface réseau pour un moment, j'ai essayé ce qui suit (j'ai surtout écarté les coupables improbables) :
- Augmentation des tampons de réception de 256 à 2k et des tampons d'émission de 512 à 2k (les deux sont actuellement au maximum) - Pas de changement
- Désactivation de tous les chargements de somme de contrôle IP/TCP/UDP. - Pas de changement.
- Désactivation de la charge d'envoi importante - Nada.
- Désactivation de l'IPv6, de la programmation QoS - Rien.
Mise à jour 3 - 3 juillet
En essayant d'éliminer le côté serveur Linux, j'ai démarré une instance de Server 2012R2 et j'ai répété les tests en utilisant iperf
(binaire cygwin) et NTttcp .
Avec iperf
J'ai dû spécifier explicitement -w1m
sur à la fois avant que la connexion n'évolue au-delà de ~5Mbit/s. (Soit dit en passant, j'ai pu vérifier que le BDP de ~5Mbits à 91ms de latence est presque précisément de 64kb. Repérer la limite...)
Les binaires ntttcp présentent désormais une telle limitation. L'utilisation de ntttcpr -m 1,0,1.2.3.5
sur le serveur et ntttcp -s -m 1,0,1.2.3.5 -t 10
sur le client, je constate une nette amélioration du débit :
Copyright Version 5.28
Network activity progressing...
Thread Time(s) Throughput(KB/s) Avg B / Compl
====== ======= ================ =============
0 9.990 8155.355 65536.000
##### Totals: #####
Bytes(MEG) realtime(s) Avg Frame Size Throughput(MB/s)
================ =========== ============== ================
79.562500 10.001 1442.556 7.955
Throughput(Buffers/s) Cycles/Byte Buffers
===================== =========== =============
127.287 308.256 1273.000
DPCs(count/s) Pkts(num/DPC) Intr(count/s) Pkts(num/intr)
============= ============= =============== ==============
1868.713 0.785 9336.366 0.157
Packets Sent Packets Received Retransmits Errors Avg. CPU %
============ ================ =========== ====== ==========
57833 14664 0 0 9.476
Avec 8MB/s, il atteint les niveaux que j'obtenais avec des Windows explicitement grands dans iperf
. Curieusement, 80MB dans 1273 buffers = un buffer de 64kB à nouveau. Un autre wireshark montre un bon RWIN variable en provenance du serveur (facteur d'échelle 256) que le client semble respecter ; donc peut-être que ntttcp signale mal la fenêtre d'envoi.
Mise à jour 4 - 3 juillet
À la demande de @karyhead, j'ai effectué quelques tests supplémentaires et généré quelques captures supplémentaires, ici : https://www.dropbox.com/s/dtlvy1vi46x75it/iperf%2Bntttcp%2Bftp-pcaps-2014-07-03.zip
- Deux de plus
iperf
tous deux de Windows vers le même serveur Linux qu'auparavant (1.2.3.4) : Une avec une taille de socket de 128k et une fenêtre par défaut de 64k (limite à ~5Mbit/s à nouveau) et une avec une fenêtre d'envoi de 1MB et une taille de socket par défaut de 8kb. (échelles plus élevées) - Un
ntttcp
trace du même client Windows vers une instance EC2 Server 2012R2 (1.2.3.5). Ici, le débit s'échelonne bien. Note : NTttcp fait quelque chose de bizarre sur le port 6001 avant d'ouvrir la connexion de test. Je ne suis pas sûr de ce qui se passe ici. - Une trace de données FTP, téléchargeant 20MB de
/dev/urandom
sur un hôte linux presque identique (1.2.3.6) en utilisant Cygwinncftp
. Là encore, il y a une limite. Le schéma est à peu près le même avec Windows Filezilla.
Changer le iperf
La longueur de la mémoire tampon apporte la différence attendue au graphique de la séquence temporelle (beaucoup plus de sections verticales), mais le débit réel reste inchangé.