Версия TL; DR
Посмотрите этот актерский состав ASCII или это видео, а затем найдите причины, по которым это происходит. Текстовое описание, которое следует, обеспечивает больше контекста.
Подробности настройки
- Machine 1 - это портативный компьютер Arch Linux, на котором
ssh
он создается, подключаясь к SBC, работающему на Armbian (Orange PI Zero). - Сам SBC подключен через Ethernet к маршрутизатору DSL и имеет IP-адрес 192.168.1.150.
- Ноутбук подключен к маршрутизатору через WiFi - с помощью официального ключа Raspberry PI WiFi.
- Есть также еще один ноутбук (машина 2), подключенный через Ethernet к маршрутизатору DSL.
Сравнительный анализ связи с iperf3
При сравнительном тестировании iperf3
связь между ноутбуком и SBC меньше теоретической скорости 56 Мбит / с, как и ожидалось, поскольку это соединение WiFi в очень «переполненном 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), но на этот раз с другой машины (машина 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 может (легко) обрабатывать 11 МБ / с (то есть 100 Мбит / с), которые обеспечивает его канал 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]
Работает! 10-кратная скорость.
Теперь я немного запутался - когда вы используете «голый» nc
как Proxycommand
разве вы не делаете в точности то же самое, что делает SSH? т.е. создать сокет, подключиться к порту 22 SBC, а затем переложить поверх него протокол SSH?
Почему такая огромная разница в скорости?
PS Это не было академическим упражнением - borg
из-за этого мое резервное копирование выполняется в 10 раз быстрее. Я просто не знаю почему :-)
РЕДАКТИРОВАТЬ : Добавлено "видео" процесса здесь . Подсчитав пакеты, отправленные с выхода ifconfig, становится ясно, что в обоих тестах мы отправляем 40 МБ данных, передавая их примерно в пакетах по 30 КБ - просто намного медленнее, когда они не используются ProxyCommand
.
источник
nc
использует буферизацию строки, аssh
не имеет буферизации. Так (или если так) трафик ssh включает больше пакетов.Ответы:
Большое спасибо людям, которые представили идеи в комментариях. Я прошел их всех:
Запись пакетов с помощью tcpdump и сравнение содержимого в WireShark
Там не было никакой разницы какой-либо важности в записанных пакетах.
Проверка на формирование трафика
Я понятия не имел об этом - но после просмотра справочной страницы "tc" я смог убедиться, что
tc filter show
ничего не возвращаетtc class show
ничего не возвращаетtc qdisc show
... возвращает это:
... которые, кажется, не делают различий между "ssh" и "nc" - на самом деле, я даже не уверен, может ли формирование трафика работать на уровне процесса (я ожидаю, что оно будет работать на адресах / портах / дифференцированных Поле служб в заголовке IP).
Debian Chroot, чтобы избежать потенциальной «хитрости» в SSH-клиенте Arch Linux
Нет, те же результаты.
Наконец - нагл
Выполняя пересылку в отправителе ...
... и, глядя на то, что именно происходит в сокете, через который передаются данные, я заметил эту «настройку» перед началом фактической передачи:
Это устанавливает сокет SSH для отключения алгоритма Nagle. Вы можете Google и прочитать все об этом - но это означает, что SSH отдает приоритет реагированию над пропускной способностью - он инструктирует ядро немедленно передавать все, что написано на этом сокете, а не «задерживать» ожидание подтверждений от удаленного устройства.
Говоря простым языком, это означает, что в конфигурации по умолчанию SSH НЕ является хорошим способом передачи данных между собой - не тогда, когда используемая связь является медленной (что имеет место для многих WiFi-соединений). Если мы отправляем по беспроводной сети пакеты, которые являются «главным образом заголовками», пропускная способность теряется!
Чтобы доказать, что это действительно было преступником, я использовал LD_PRELOAD, чтобы «удалить» этот конкретный системный вызов:
Там - идеальная скорость (ну так же быстро, как и iperf3).
Мораль истории
Никогда не сдавайся :-)
И если вы используете такие инструменты
rsync
или такие,borgbackup
которые передают их данные через SSH, и ваша ссылка медленная, попробуйте не использовать SSH для отключения Nagle (как показано выше) - или использоватьProxyCommand
для переключения SSH для подключения черезnc
. Это можно автоматизировать в вашем $ HOME / .ssh / config:... так что все будущие использования "orangepi" в качестве целевого хоста в ssh / rsync / borgbackup впредь будут использоваться
nc
для подключения (и, следовательно, оставлять Nagle в покое).источник