A versão TL;DR
Assista a este elenco ASCII ou a este vídeo - e depois pense em algum motivo para isso estar acontecendo. A descrição do texto a seguir fornece mais contexto.
Detalhes da configuração
- A máquina 1 é um laptop Arch Linux, no qual
ssh
é gerado, conectando-se a um SBC executando Armbian (um Orange PI Zero). - O próprio SBC está conectado via Ethernet a um roteador DSL e possui um IP de 192.168.1.150
- O laptop está conectado ao roteador por WiFi - usando um dongle Raspberry PI WiFi oficial.
- Há também outro laptop (Máquina 2) conectado via Ethernet ao roteador DSL.
Fazendo benchmarking do link com iperf3
Quando comparado com iperf3
o , o link entre o laptop e o SBC é menor que os 56 MBits/s teóricos - como esperado, já que se trata de uma conexão Wi-Fi dentro de um "2,4 GHz" muito "lotado" (prédio de apartamentos) .
Mais especificamente: após a execução iperf3 -s
no SBC, os seguintes comandos são executados no laptop:
# 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
Então, basicamente, o upload para o SBC atinge cerca de 24 MBits/s e o download dele ( -R
) atinge 32 MBits/s.
Benchmarking com SSH
Dado isso, vamos ver como o SSH se sai. Eu experimentei pela primeira vez os problemas que levaram a esta postagem ao usar rsync
e borgbackup
- ambos usando SSH como uma camada de transporte ... Então, vamos ver como o SSH funciona no mesmo link:
# cat /dev/urandom | \
pv -ptebar | \
ssh [email protected] 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]
Bem, isso é uma velocidade abismal! Muito mais lento que a velocidade de link esperada...
(Caso você não saiba pv -ptevar
: ele exibe a taxa atual e média de dados passando por ele. Nesse caso, vemos que ler /dev/urandom
e enviar os dados por SSH para o SBC atinge, em média, 400 KB/s - ou seja, 3,2 MBits/s, um valor bem menor do que os 24 MBits/s esperados.)
Por que nosso link está operando a 13% de sua capacidade?
É talvez nossa /dev/urandom
culpa?
# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]
Não, definitivamente não.
É talvez o próprio SBC? Talvez seja muito lento para processar? Vamos tentar executar o mesmo comando SSH (ou seja, enviar dados para o SBC), mas desta vez de outra máquina (Máquina 2) conectada pela Ethernet:
# cat /dev/urandom | \
pv -ptebar | \
ssh [email protected] 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s]
Não, isso funciona bem - o daemon SSH no SBC pode (facilmente) lidar com 11 MBytes/seg (ou seja, 100 MBits/seg) que seu link Ethernet fornece.
E a CPU do SBC é carregada ao fazer isso?
Não.
Então...
- em termos de rede (conforme
iperf3
), devemos ser capazes de fazer 10x a velocidade - nossa CPU pode facilmente acomodar a carga
- ... e não envolvemos nenhum outro tipo de E/S (por exemplo, drives).
O que diabos está acontecendo?
Netcat e ProxyCommand para o resgate
Vamos tentar netcat
conexões antigas simples - elas rodam tão rápido quanto esperávamos?
No SBC:
# nc -l -p 9988 | pv -ptebar > /dev/null
No portátil:
# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s]
Funciona! E roda na velocidade esperada - muito melhor, 10x melhor.
Então, o que acontece se eu executar o SSH usando um ProxyCommand para usar o 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]
Funciona! velocidade 10x.
Agora estou um pouco confuso - ao usar um "naked" nc
como um Proxycommand
, você não está basicamente fazendo exatamente a mesma coisa que o SSH faz? ou seja, criar um soquete, conectar-se à porta 22 do SBC e, em seguida, transferir o protocolo SSH sobre ele?
Por que existe essa enorme diferença na velocidade resultante?
PS Este não foi um exercício acadêmico - meu borg
backup é executado 10 vezes mais rápido por causa disso. Só não sei porque :-)
EDIT : Adicionado um "vídeo" do processo aqui . Contando os pacotes enviados da saída do ifconfig, fica claro que em ambos os testes estamos enviando 40MB de dados, transmitindo-os em aproximadamente 30K pacotes - só que bem mais lento quando não estamos usando ProxyCommand
.