Wersja TL; DR
Obejrzyj tę obsadę ASCII lub wideo - a następnie wymyśl wszelkie powody, dla których tak się dzieje. Poniższy opis tekstowy zapewnia większy kontekst.
Szczegóły konfiguracji
- Maszyna 1 to laptop Arch Linux, na którym
ssh
odradza się, łączący się z SBC działającym pod kontrolą Armbiana (Orange PI Zero). - Sam SBC jest podłączony przez Ethernet do routera DSL i ma adres IP 192.168.1.150
- Laptop jest podłączony do routera przez WiFi - za pomocą oficjalnego klucza Raspberry PI WiFi.
- Istnieje również inny laptop (Maszyna 2) podłączony przez Ethernet do routera DSL.
Benchmarking linku za pomocą iperf3
W testach porównawczych iperf3
połączenie między laptopem a SBC jest mniejsze niż teoretyczne 56 MB / s - zgodnie z oczekiwaniami, ponieważ jest to połączenie Wi-Fi w bardzo „zatłoczonym 2,4 GHz” (budynek mieszkalny) .
Mówiąc dokładniej: po uruchomieniu iperf3 -s
na SBC na laptopie wykonywane są następujące polecenia:
# 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
W zasadzie przesyłanie do SBC osiąga około 24 MB / s, a pobieranie z niego ( -R
) osiąga 32 MB / s.
Benchmarking z SSH
Biorąc to pod uwagę, zobaczmy, jak radzi sobie SSH. Najpierw doświadczyłem problemów, które doprowadziły do tego postu podczas używania rsync
i borgbackup
- oba używają SSH jako warstwy transportowej ... Zobaczmy więc, jak SSH działa na tym samym łączu:
# cat /dev/urandom | \
pv -ptebar | \
ssh [email protected] 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]
To niesamowita prędkość! Znacznie wolniejsza niż oczekiwana prędkość łącza ...
(W przypadku, gdy nie jesteś świadomy pv -ptevar
: wyświetla bieżącą i średnią szybkość danych przez nią przechodzących. W tym przypadku widzimy, że odczytuje /dev/urandom
i wysyła dane przez SSH do SBC osiąga średnio 400 KB / s - tj. 3,2 MB / s, czyli znacznie mniej niż oczekiwane 24 MB / s.)
Dlaczego nasze łącze działa przy 13% swojej pojemności?
Czy to może nasza /dev/urandom
wina?
# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]
Nie, zdecydowanie nie.
Czy to może sama SBC? Być może jest zbyt wolny do przetworzenia? Spróbujmy uruchomić to samo polecenie SSH (tj. Wysłać dane do SBC), ale tym razem z innej maszyny (Maszyna 2), która jest podłączona przez Ethernet:
# cat /dev/urandom | \
pv -ptebar | \
ssh [email protected] 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s]
Nie, to działa dobrze - demon SSH na SBC może (łatwo) obsłużyć 11 MB / s (tj. 100 MB / s), które zapewnia łącze Ethernet.
I czy podczas tego procesu ładowany jest procesor SBC?
Nie.
Więc...
- pod względem sieci (zgodnie z
iperf3
) powinniśmy być w stanie osiągnąć 10-krotną prędkość - nasz procesor może łatwo wytrzymać obciążenie
- ... i nie angażujemy żadnego innego rodzaju We / Wy (np. dysków).
Co się do cholery dzieje?
Netcat i ProxyCommand na ratunek
Wypróbujmy stare, proste netcat
połączenia - czy działają tak szybko, jak byśmy się spodziewali?
W SBC:
# nc -l -p 9988 | pv -ptebar > /dev/null
W laptopie:
# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s]
To działa! I działa z oczekiwaną - znacznie lepszą, 10-krotnie lepszą - prędkością.
Co się stanie, jeśli uruchomię SSH za pomocą ProxyCommand, aby użyć 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]
Pracuje! 10-krotna prędkość.
Teraz jestem trochę zdezorientowany - kiedy używasz „nagiego” nc
jako Proxycommand
, czy zasadniczo nie robisz dokładnie tego samego, co robi SSH? tj. utworzenie gniazda, połączenie z portem SBC 22, a następnie przerzucenie protokołu SSH nad nim?
Dlaczego jest tak ogromna różnica w wynikowej prędkości?
PS To nie było ćwiczenie akademickie - borg
z tego powodu moja kopia zapasowa działa 10 razy szybciej. Po prostu nie wiem dlaczego :-)
EDIT : Dodano „Video” procesu tutaj . Licząc pakiety wysłane z wyjścia ifconfig, jasne jest, że w obu testach wysyłamy 40 MB danych, przesyłając je w pakietach około 30 KB - po prostu znacznie wolniej, gdy nie są używane ProxyCommand
.
źródło
nc
używa buforowania linii, podczas gdyssh
nie ma buforowania. Tak więc (lub jeśli tak) ruch ssh obejmuje więcej pakietów.Odpowiedzi:
Ogromne podziękowania dla osób, które zgłosiły pomysły w komentarzach. Przejrzałem je wszystkie:
Nagrywanie pakietów za pomocą tcpdump i porównywanie zawartości w WireShark
W zarejestrowanych pakietach nie było żadnej różnicy.
Sprawdzanie kształtowania ruchu
Nie miałem o tym pojęcia - ale po przejrzeniu strony „tc” udało mi się to zweryfikować
tc filter show
nic nie zwracatc class show
nic nie zwracatc qdisc show
... zwraca te:
... które wydają się nie rozróżniać między "ssh" i "nc" - w rzeczywistości nie jestem nawet pewien, czy kształtowanie ruchu może działać na poziomie procesu (oczekiwałbym, że będzie działać na adresach / portach / Zróżnicowany Pole Usługi w nagłówku IP).
Debian Chroot, aby uniknąć potencjalnej „sprytności” w kliencie SSH Arch Linux
Nie, te same wyniki.
Wreszcie - Nagle
Przeprowadzanie śledzenia nadawcy ...
... i patrząc na to, co dokładnie dzieje się w gnieździe, przez które przesyłane są dane, zauważyłem tę „konfigurację” przed rozpoczęciem faktycznego przesyłania:
To ustawia gniazdo SSH w celu wyłączenia algorytmu Nagle. Możesz Google i przeczytać o tym wszystko - ale to znaczy, że SSH daje pierwszeństwo responsywności nad przepustowością - instruuje jądro, aby natychmiast przesyłało wszystko, co napisano na tym gnieździe, a nie „opóźniało” oczekiwanie na potwierdzenia z pilota.
Mówiąc wprost, oznacza to, że w domyślnej konfiguracji, SSH NIE jest dobrym sposobem na przesyłanie danych - nie wtedy, gdy używane łącze jest wolne (co ma miejsce w przypadku wielu łączy WiFi). Jeśli wysyłamy pakiety bezprzewodowo, które są „głównie nagłówkami”, przepustowość jest marnowana!
Aby udowodnić, że to rzeczywiście był winowajca, użyłem LD_PRELOAD, aby „upuścić” ten konkretny system:
Tam - idealna prędkość (cóż, tak szybko jak iperf3).
Morale tej historii
Nigdy się nie poddawaj :-)
A jeśli korzystasz z takich narzędzi
rsync
lub takich,borgbackup
które przenoszą ich dane przez SSH, a twój link jest wolny, spróbuj powstrzymać SSH przed wyłączeniem Nagle (jak pokazano powyżej) - lub użyjProxyCommand
przełączania SSH do łączenia się za pośrednictwemnc
. Można to zautomatyzować w $ HOME / .ssh / config:... dzięki czemu wszystkie przyszłe zastosowania „orangepi” jako hosta docelowego w ssh / rsync / borgbackup będą odtąd używane
nc
do łączenia się (a zatem zostawiają Nagle w spokoju).źródło