La version TL; DR
Regardez cette distribution ASCII ou cette vidéo - puis trouvez les raisons pour lesquelles cela se produit. La description textuelle qui suit fournit plus de contexte.
Détails de l'installation
- La machine 1 est un ordinateur portable Arch Linux, sur lequel
ssh
est généré, se connectant à un SBC fonctionnant sous Armbian (un Orange PI Zero). - Le SBC lui-même est connecté via Ethernet à un routeur DSL et a une IP de 192.168.1.150
- L'ordinateur portable est connecté au routeur via WiFi - à l'aide d'un dongle WiFi Raspberry PI officiel.
- Il y a aussi un autre ordinateur portable (Machine 2) connecté via Ethernet au routeur DSL.
Analyse comparative du lien avec iperf3
Lorsque comparé avec iperf3
, le lien entre l'ordinateur portable et le SBC est inférieur aux 56 Mbits / s théoriques - comme prévu, car il s'agit d'une connexion WiFi dans un 2,4 GHz très fréquenté (immeuble à appartements) .
Plus précisément: après exécution iperf3 -s
sur le SBC, les commandes suivantes sont exécutées sur l'ordinateur portable:
# iperf3 -c 192.168.1.150
Connecting to host 192.168.1.150, port 5201
[ 5] local 192.168.1.89 port 57954 connected to 192.168.1.150 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 2.99 MBytes 25.1 Mbits/sec 0 112 KBytes
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 28.0 MBytes 23.5 Mbits/sec 5 sender
[ 5] 0.00-10.00 sec 27.8 MBytes 23.4 Mbits/sec receiver
iperf Done.
# iperf3 -c 192.168.1.150 -R
Connecting to host 192.168.1.150, port 5201
Reverse mode, remote host 192.168.1.150 is sending
[ 5] local 192.168.1.89 port 57960 connected to 192.168.1.150 port 5201
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 3.43 MBytes 28.7 Mbits/sec
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 39.2 MBytes 32.9 Mbits/sec 375 sender
[ 5] 0.00-10.00 sec 37.7 MBytes 31.6 Mbits/sec receiver
Donc, fondamentalement, le téléchargement vers le SBC atteint environ 24 Mo / s, et le téléchargement depuis ( -R
) atteint 32 Mo / s.
Analyse comparative avec SSH
Cela étant, voyons comment s'en sort SSH. J'ai d'abord rencontré les problèmes qui ont conduit à ce message lors de l'utilisation rsync
et borgbackup
- les deux utilisant SSH comme couche de transport ... Voyons donc comment SSH fonctionne sur le même lien:
# cat /dev/urandom | \
pv -ptebar | \
ssh [email protected] 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]
Eh bien, c'est une vitesse abyssale! Beaucoup plus lent que la vitesse de liaison attendue ...
(Dans le cas où vous n'êtes pas au courant pv -ptevar
: il affiche le débit actuel et moyen des données qui le traversent. Dans ce cas, nous voyons que la lecture /dev/urandom
et l'envoi des données via SSH au SBC atteint en moyenne 400 Ko / s, soit 3,2 Mo / s, un chiffre bien inférieur aux 24 Mo / s attendus.)
Pourquoi notre lien fonctionne-t-il à 13% de sa capacité?
Est-ce peut-être de notre /dev/urandom
faute?
# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]
Non, certainement pas.
Est-ce peut-être le SBC lui-même? Peut-être que c'est trop lent à traiter? Essayons d'exécuter la même commande SSH (c'est-à-dire l'envoi de données au SBC) mais cette fois à partir d'une autre machine (Machine 2) connectée via Ethernet:
# cat /dev/urandom | \
pv -ptebar | \
ssh [email protected] 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s]
Non, cela fonctionne bien - le démon SSH sur le SBC peut (facilement) gérer les 11 Mo / s (c'est-à-dire les 100 Mo / s) fournis par sa liaison Ethernet.
Et le CPU du SBC est-il chargé en faisant cela?
Nan.
Donc...
- en termes de réseau (selon
iperf3
), nous devrions être en mesure de faire 10 fois la vitesse - notre CPU peut facilement supporter la charge
- ... et nous n'impliquons aucun autre type d'E / S (par exemple des disques).
Qu'est-ce qui se passe?
Netcat et ProxyCommand à la rescousse
Essayons de simples anciennes netcat
connexions - fonctionnent-elles aussi vite que prévu?
Dans le SBC:
# nc -l -p 9988 | pv -ptebar > /dev/null
Dans l'ordinateur portable:
# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s]
Ça marche! Et fonctionne à la vitesse attendue - bien meilleure, 10 fois meilleure -.
Alors, que se passe-t-il si j'exécute SSH à l'aide d'un ProxyCommand pour utiliser nc?
# cat /dev/urandom | \
pv -ptebar | \
ssh -o "Proxycommand nc %h %p" [email protected] 'cat >/dev/null'
101MiB 0:00:30 [3.38MiB/s] [3.33MiB/s]
Travaux! Vitesse 10x.
Maintenant, je suis un peu confus - lorsque vous utilisez un "nu" nc
comme Proxycommand
, ne faites-vous pas exactement la même chose que SSH? c'est-à-dire créer un socket, se connecter au port 22 du SBC, puis pelleter le protocole SSH dessus?
Pourquoi y a-t-il cette énorme différence dans la vitesse résultante?
PS Ce n'était pas un exercice académique - ma borg
sauvegarde s'exécute 10 fois plus vite à cause de cela. Je ne sais juste pas pourquoi :-)
EDIT : Ajout d'une "vidéo" du processus ici . En comptant les paquets envoyés à partir de la sortie d'ifconfig, il est clair que dans les deux tests, nous envoyons 40 Mo de données, les transmettant dans environ 30 000 paquets - juste beaucoup plus lentement lorsque vous ne les utilisez pas ProxyCommand
.
la source
nc
utilise la mise en mémoire tampon de ligne, alors qu'ilssh
n'a pas de mise en mémoire tampon. Donc (ou si c'est le cas) le trafic ssh implique plus de paquets.Réponses:
Un grand merci aux personnes qui ont soumis des idées dans les commentaires. Je les ai tous passés en revue:
Enregistrement de paquets avec tcpdump et comparaison du contenu dans WireShark
Il n'y avait aucune différence d'importance dans les paquets enregistrés.
Vérification de la mise en forme du trafic
Je n'en avais aucune idée - mais après avoir regardé la page de manuel "tc", j'ai pu vérifier que
tc filter show
ne renvoie rientc class show
ne renvoie rientc qdisc show
... les renvoie:
... qui ne semblent pas faire la différence entre "ssh" et "nc" - en fait, je ne suis même pas sûr que la mise en forme du trafic puisse fonctionner au niveau du processus (je m'attendrais à ce qu'il fonctionne sur les adresses / ports / différenciés Champ Services dans l'en-tête IP).
Debian Chroot, pour éviter une potentielle "intelligence" dans le client Arch Linux SSH
Non, mêmes résultats.
Enfin - Nagle
Exécution d'une séquence dans l'expéditeur ...
... et en regardant ce qui se passe exactement sur le socket qui transmet les données, j'ai remarqué cette "configuration" avant le début de la transmission:
Cela configure le socket SSH pour désactiver l'algorithme de Nagle. Vous pouvez Google et tout lire à ce sujet - mais ce que cela signifie, c'est que SSH donne la priorité à la réactivité sur la bande passante - il demande au noyau de transmettre immédiatement tout ce qui est écrit sur cette socket et de ne pas "retarder" l'attente des accusés de réception de la télécommande.
Cela signifie, en termes simples, que dans sa configuration par défaut, SSH n'est PAS un bon moyen de transporter des données à travers - pas lorsque le lien utilisé est lent (ce qui est le cas pour de nombreux liens WiFi). Si nous envoyons des paquets en direct qui sont "principalement des en-têtes", la bande passante est gaspillée!
Pour prouver que c'était bien le coupable, j'ai utilisé LD_PRELOAD pour "supprimer" cet appel système spécifique:
Là - vitesse parfaite (enfin, aussi rapide que iperf3).
Moral de l'histoire
N'abandonnez jamais :-)
Et si vous utilisez des outils comme
rsync
ouborgbackup
qui transportent leurs données sur SSH, et que votre lien est lent, essayez d'empêcher SSH de désactiver Nagle (comme illustré ci-dessus) - ou utilisezProxyCommand
pour basculer SSH pour vous connecter vianc
. Cela peut être automatisé dans votre $ HOME / .ssh / config:... afin que toutes les utilisations futures de "orangepi" comme hôte cible dans ssh / rsync / borgbackup soient désormais utilisées
nc
pour se connecter (et donc laisser Nagle tranquille).la source