Misura la latenza totale della sessione SSH


15

Esiste un modo per misurare / segnalare la latenza complessiva in una sessione SSH con tunnel?

La mia configurazione particolare è:

  • Client (OS X + router wifi + modem ADSL)
  • Server SSH gateway esposto a Internet
  • Target SSH interno a cui sto effettuando il tunneling

Sono interessato a vedere la latenza tra la console sul mio computer locale e il computer finale su cui ho aperto la sessione.


Perché non eseguire il tunneling SSH sul primo server e quindi sulla console SSH sul secondo server.
Bert

Risposte:


6

Stavo provando a farlo da solo e ho pensato a questo. Probabilmente esiste un modo più semplice, ma questo è quello che mi è venuto in mente.

Innanzitutto, preparare le pipe che verranno utilizzate per comunicare il programma di benchmarking attraverso la connessione SSH.

$ mkfifo /tmp/up /tmp/down

Quindi stabilire una connessione in modalità ControlMaster senza eseguire alcun comando remoto. Questo ci consente di autenticarci in modo interattivo con l'host. Dopo aver stabilito la connessione, SSH si "bloccherà" qui in primo piano.

$ ssh $HOST -N -M -S /tmp/control

In un terminale parallelo, eseguire il telecomando catin background. Sarà il nostro server di eco di cui misureremo la latenza. Ingressi e uscite sono collegati a FIFO:

$ ssh $HOST -S /tmp/control cat </tmp/up >/tmp/down &

Quindi confronta un piccolo programma (invia un byte a upFIFO, ricevi un byte da downFIFO):

$ python -m timeit -s 'import os' \
    'os.write(3, "z"); z=os.read(4, 1); assert z=="z", "got %s" % z' \
    3>/tmp/up 4</tmp/down
10 loops, best of 3: 24.6 msec per loop

La misura mostra ovviamente la latenza di andata e ritorno. Se devi ripetere l'esperimento, esegui di nuovo gli ultimi due comandi ( sshe python).

Se qualcosa sembra andare storto, utilizzare il -vflag SSH per ottenere più output di debug.


4

Ho saltato alcuni passaggi suggeriti da @nicht-verstehen:

python -m timeit --setup 'import subprocess; p = subprocess.Popen(["ssh", "user@host", "cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0)' 'p.stdin.write(b"z"); assert p.stdout.read(1) == b"z"'

Dove

python -m timeitesegue il timeitmodulo Python.

L' -s/--setupopzione indica timeitquali istruzioni eseguire prima di ogni ripetizione.

subprocess.Popen(["ssh", "user@host", "cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0)si avvia ssh- eseguendo catsul proprio host - come figlio / sottoprocesso, reindirizzando i suoi flussi IO su oggetti simili a file Python. bufsize=0si assicura che nessun IO sia bufferizzato, il che può causare IO in attesa.

E per ogni ciclo:
p.stdin.write(b"z")scrive un singolo byte sul figlio (a sua volta tramite ssh a cat).
p.stdout.read(1)legge un singolo byte dal figlio. L'asserzione attorno ad esso verifica se quel byte è lo stesso di quello che gli hai scritto.

Si riduce alla stessa cosa, ma salta creando le named pipe ( mkfifo). Ho notato che più loop esegui, più veloce è ogni loop. Controllalo usando -n/--number:python -m timeit --number 50 ...


3

Vedi l' sshpingutilità: https://github.com/spook/sshping

Esempio:

# sshping 172.16.47.143
--- Login: 1725 msec
--- Minimum Latency: 4046 nsec
---  Median Latency: 11026 nsec  +/- 0 std dev
--- Average Latency: 178105 nsec
--- Maximum Latency: 8584886 nsec
---      Echo count: 1000 Bytes
---  Transfer Speed: 11694919 Bytes/second

# sshping --help
Usage: sshping [options] [user@]addr[:port]

  SSH-based ping that measures interactive character echo latency
  and file transfer throughput.  Pronounced "shipping".

Options:
  -c  --count NCHARS   Number of characters to echo, default 1000
  -e  --echocmd CMD    Use CMD for echo command; default: cat > /dev/null
  -h  --help           Print usage and exit
  -i  --identity FILE  Identity file, ie ssh private keyfile
  -p  --password PWD   Use password PWD (can be seen, use with care)
  -r  --runtime SECS   Run for SECS seconds, instead of count limit
  -t  --tests e|s      Run tests e=echo s=speed; default es=both
  -v  --verbose        Show more output, use twice for more: -vv

0

La mia idea era di usare sequenze di query terminali per questo; il vantaggio è che questo può essere semplicemente eseguito sul server, lo svantaggio è che misura la latenza del terminale, non solo la latenza della connessione (ma immagino, di solito, il tempo di risposta del tuo terminale sarà trascurabile rispetto ai ritardi della rete) - forse questo è anche ciò che intendi con latenza generale

#!/usr/bin/env python3
# Measure terminal latency (round-trip time) using "Query device code" command
from sys import stdin, stdout
import tty, termios, time

oldtty = termios.tcgetattr(stdin)
try:
    tty.setcbreak(stdout)

    runs = 10
    results = []
    for _ in range(runs):
        stdout.write("\x1b[c")
        stdout.flush()
        t1 = time.time()
        ch = stdin.read(1)
        assert(ch == '\x1b')
        t2 = time.time()
        while stdin.read(1) != 'c': # swallow rest of report
            continue
        latency = (t2 - t1) * 1000
        print('%.1fms' % (latency))
        results.append(latency)

    print()
    print('avg: %.1fms min: %.1fms max: %.1fms' % (
        sum(results) / runs,
        min(results),
        max(results)))
finally:
    termios.tcsetattr(stdin, termios.TCSADRAIN, oldtty)

(Questo utilizza "Device Code Query", tutti i terminali che ho provato a rispondere a questo: xterm, alacritty, gnome-terminal. Non posso provare questo su MacOS. Quindi YMMV, se questo non lo fa, un'altra delle richieste che interrogare alcune informazioni sul terminale potrebbe funzionare, consultare http://www.termsys.demon.co.uk/vtansi.htm )


1
Questa risposta potrebbe ancora usare qualche spiegazione per coloro che non hanno familiarità con i tty internals (ad esempio, perché \x1b[csarebbe favorevole)
anx

non sono sicuro che sia favorevole, penso che sia una discussione valida: qualsiasi dal "Status del dispositivo" termsys.demon.co.uk/vtansi.htm funzionerebbe, dato che il terminale lo supporta, e non ho idea di cosa sia ben supportato, ma la mia ipotesi è che la query sullo stato di base sarebbe (funziona anche con Alacritty bare-bones)
wump
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.