Версія TL; DR
Перегляньте цей акторський фільм ASCII або це відео - тоді придумайте будь-які причини, чому це відбувається. Наступний опис тексту надає більше контексту.
Деталі налаштування
- Машина 1 - це ноутбук Arch Linux, на якому
ssh
нерегулярно підключається до підключеного Armbian SBC (Orange PI Zero). - Сам SBC підключений через Ethernet до маршрутизатора DSL і має IP 192.168.1.150
- Ноутбук підключений до маршрутизатора через WiFi - за допомогою офіційного ключа Wi-Fi Raspberry PI.
- Також є ще один ноутбук (машина 2), підключений через Ethernet до маршрутизатора DSL.
Бенчмаркінг посилання на iperf3
Якщо орієнтуватися на iperf3
, зв'язок між ноутбуком та SBC менший, ніж теоретичні 56 Мбіт / с - як очікувалося, оскільки це підключення до Wi-Fi у дуже "переповненому 2,4 ГГц" (багатоквартирний будинок) .
Більш конкретно: після запуску iperf3 -s
на SBC на ноутбуці виконуються такі команди:
# 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
Таким чином, завантаження в SBC досягає приблизно 24 Мбіт / сек, а завантаження з нього ( -R
) досягає 32 Мбіт / сек.
Бенчмаркінг із SSH
Враховуючи це, давайте подивимось, як проходить SSH. Я вперше зіткнувся з проблемами, які спричинили цю публікацію при використанні, rsync
і borgbackup
- обидва вони використовують SSH як транспортний шар ... Тож давайте подивимось, як SSH працює на одному посиланні:
# cat /dev/urandom | \
pv -ptebar | \
ssh root@192.168.1.150 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]
Ну, це безглузда швидкість! Набагато повільніше, ніж очікувана швидкість зв'язку ...
(Якщо ви цього не знаєте pv -ptevar
: він відображає поточну та середню швидкість передачі даних, що проходять через неї. У цьому випадку ми бачимо, що читаємо /dev/urandom
і передаємо дані через SSH в SBC в середньому досягає 400 КБ / с - тобто 3,2 Мбіт / сек, що набагато менший показник, ніж очікувані 24 Мбіт / сек.)
Чому наше посилання працює на 13% від його потужності?
Чи, можливо, ми /dev/urandom
винні в цьому?
# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]
Ні, точно.
Це, можливо, сам SBC? Можливо, це занадто повільно обробляти? Спробуємо запустити ту саму команду SSH (тобто надсилання даних в SBC), але цього разу з іншої машини (Machine 2), підключеної через Ethernet:
# cat /dev/urandom | \
pv -ptebar | \
ssh root@192.168.1.150 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s]
Ні, це працює чудово - демон SSH на SBC може (легко) обробляти 11MBytes / sec (тобто 100MBits / sec), які надає Ethernet-посилання.
І чи завантажується процесор SBC, роблячи це?
Ні.
Так...
- мережево (відповідно до
iperf3
) ми повинні мати можливість робити 10-кратну швидкість - наш процесор може легко вмістити навантаження
- ... і ми не залучаємо жодного іншого типу вводу-виводу (наприклад, накопичувачі).
Що, до біса, відбувається?
Netcat і ProxyCommand на допомогу
Давайте спробуємо звичайні старі netcat
з'єднання - чи вони працюють так швидко, як ми очікували?
У SBC:
# nc -l -p 9988 | pv -ptebar > /dev/null
У ноутбуці:
# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s]
Це працює! І працює з очікуваною - набагато кращою, в 10 разів кращою - швидкістю.
Що ж станеться, якщо я запускаю SSH за допомогою ProxyCommand для використання nc?
# cat /dev/urandom | \
pv -ptebar | \
ssh -o "Proxycommand nc %h %p" root@192.168.1.150 'cat >/dev/null'
101MiB 0:00:30 [3.38MiB/s] [3.33MiB/s]
Працює! 10x швидкість.
Тепер я трохи розгублений - коли ви використовуєте "голий" nc
як a Proxycommand
, чи не в основному ви робите саме те, що робить SSH? тобто створити сокет, підключитися до порту 22 SBC, а потім перенести через нього протокол SSH?
Чому існує така величезна різниця в отриманій швидкості?
PS Це була не академічна вправа - borg
завдяки цьому моя резервна копія працює в 10 разів швидше. Я просто не знаю, чому :-)
EDIT : долучення «відео» процесу тут . Підраховуючи пакети, надіслані з виводу ifconfig, зрозуміло, що в обох тестах ми надсилаємо 40 Мб даних, передаючи їх приблизно в 30 К пакетів - просто набагато повільніше, коли не використовуємо ProxyCommand
.
nc
використовує буферизацію ліній, тоді якssh
буферизація не має. Так (або якщо так), ssh трафік включає більше пакетів.