La versión TL; DR
Mire este elenco de ASCII o este video , luego descubra cualquier razón por la que esto está sucediendo. La descripción del texto que sigue proporciona más contexto.
Detalles de la configuración
- Machine 1 es una computadora portátil Arch Linux, en la cual
ssh
se genera, conectándose a un SBC que funciona con Armbian (un Orange PI Zero). - El SBC está conectado a través de Ethernet a un enrutador DSL y tiene una IP de 192.168.1.150
- La computadora portátil está conectada al enrutador a través de WiFi, utilizando un dongle oficial Raspberry PI WiFi.
- También hay otra computadora portátil (Máquina 2) conectada a través de Ethernet al enrutador DSL.
Evaluación comparativa del enlace con iperf3
Cuando se compara con iperf3
, el enlace entre la computadora portátil y el SBC es inferior a los 56 MBits / seg teóricos, como se esperaba, ya que se trata de una conexión WiFi dentro de un " edificio de apartamentos " muy "abarrotado de 2,4 GHz" .
Más específicamente: después de ejecutar iperf3 -s
en el SBC, los siguientes comandos se ejecutan en la computadora portátil:
# 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
Básicamente, la carga en el SBC alcanza aproximadamente 24 MBits / seg, y la descarga desde este ( -R
) alcanza los 32 MBits / seg.
Benchmarking con SSH
Dado eso, veamos cómo le va a SSH. La primera vez que experimenté los problemas que llevaron a esta publicación fue cuando usé rsync
y borgbackup
, ambos usaron SSH como capa de transporte ... Entonces, veamos cómo SSH se desempeña en el mismo enlace:
# cat /dev/urandom | \
pv -ptebar | \
ssh root@192.168.1.150 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]
Bueno, eso es una velocidad abismal! Mucho más lento que la velocidad de enlace esperada ...
(En caso de que no lo sepa pv -ptevar
: muestra la velocidad actual y promedio de datos que lo atraviesan. En este caso, vemos que leer /dev/urandom
y enviar los datos a través de SSH al SBC en promedio alcanza los 400 KB / s, es decir, 3.2 MBits / seg, una cifra mucho menor que los 24 MBits / seg esperados).
¿Por qué nuestro enlace funciona al 13% de su capacidad?
¿Acaso /dev/urandom
es culpa nuestra ?
# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]
No, definitivamente no.
¿Es quizás el SBC mismo? ¿Quizás es demasiado lento para procesar? Intentemos ejecutar el mismo comando SSH (es decir, enviar datos al SBC) pero esta vez desde otra máquina (Máquina 2) que está conectada a través de 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]
No, esto funciona bien: el demonio SSH en el SBC puede (fácilmente) manejar los 11 MB / s (es decir, los 100 MB / s) que proporciona su enlace Ethernet.
¿Y se carga la CPU del SBC al hacer esto?
No
Entonces...
- En cuanto a la red (según
iperf3
), deberíamos poder hacer 10 veces la velocidad - nuestra CPU puede acomodar fácilmente la carga
- ... y no involucramos ningún otro tipo de E / S (por ejemplo, unidades).
¿Qué diablos está pasando?
Netcat y ProxyCommand al rescate
Probemos simplemente viejo netcat
conexiones : ¿funcionan tan rápido como podríamos esperar?
En el SBC:
# nc -l -p 9988 | pv -ptebar > /dev/null
En la laptop:
# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s]
¡Funciona! Y funciona a la velocidad esperada, mucho mejor, 10 veces mejor.
Entonces, ¿qué sucede si ejecuto SSH usando un ProxyCommand para usar 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]
¡Trabajos! 10x velocidad.
Ahora estoy un poco confundido, cuando uso un "desnudo" nc
comoProxycommand
, ¿no estás haciendo exactamente lo mismo que hace SSH? es decir, ¿crear un socket, conectarse al puerto 22 del SBC y luego traspasar el protocolo SSH?
¿Por qué hay esta gran diferencia en la velocidad resultante?
PD: Este no fue un ejercicio académico : mi borg
copia de seguridad se ejecuta 10 veces más rápido debido a esto. Simplemente no sé por qué :-)
EDITAR : Se agregó un "video" del proceso aquí . Contando los paquetes enviados desde la salida de ifconfig, está claro que en ambas pruebas estamos enviando 40MB de datos, transmitiéndolos en aproximadamente 30K paquetes, solo que mucho más lento cuando no se usa ProxyCommand
.
nc
usa buffering de línea, mientras quessh
no tiene buffering. Entonces (o si es así) el tráfico ssh involucra más paquetes.