Gerade wenn man mit verteilten Computersystemen (z. B. Cluster) arbeitet, spielt die Latenz des Netzwerkes eine große Rolle, wenn es um sachen Performance geht.

Eventuell dauert die Replikation der Datenbank nicht lange, weil die Platten dicht sind, sondern einfach weil die Latenz zu Groß ist, oder die Verbindung einen hohen Package Loss aufweist.

Grund genug also zu testen, ab welcher Latenz oder Bandbreite es kritsch wird und ob etwas am Setup optimiert werden kann/sollte.

Zum Glück kann man in Linux, mit dem Tool tc, sehr einfach Manipulationen am Netzwerk durchführen.

Um den Versuch durchzuführen, benötigt man zwei oder mehr Systeme. Zusätzlich sollte man sich überlegen, welche Metriken man im Auge behalten möchte. Stauen sich irgendwo Dateien an, welche kopiert werden sollten? Bricht die Performance der Datenbank Replikation ein? Und so weiter...

Aufbau der Testumgebung

Ich nutze bei mir zwei VMs. Auf der einen lasse ich einen Webserver laufen und werde die Netzwerk-Manipulationen durchführen.

Die zweite Maschine wird die Daten mit wget herunterladen. Dies ist natürlich nur ein ganz simples Setup...

Erstellung der Testdatei

Als erstes müssen wir uns eine Datei erstellen, welche wir später über einen Webserver zum Download anbieten. Ich erstelle in meinem Beispiel einfach eine Datei mit einer Größe von 250MB.

root@ubuntu-1gb-fra1-02:/var/www/html# dd if=/dev/zero of=250mb.test bs=10485760 count=25
25+0 records in
25+0 records out
262144000 bytes (262 MB, 250 MiB) copied, 0.43299 s, 605 MB/s

Um später einen Vergleich machen zu können, lade ich diese Datei nun erst einmal herunter.

root@ubuntu-1gb-fra1-01:~# wget http://10.10.209.87/250mb.test
--2017-08-16 18:44:21--  http://10.10.209.87/250mb.test
Connecting to 10.10.209.87:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 262144000 (250M)
Saving to: ‘250mb.test’

250mb.test      100%[===========================>] 250.00M  89.0MB/s    in 2.8s

2017-08-16 18:44:24 (89.0 MB/s) - ‘250mb.test’ saved [262144000/262144000]

Zusätzlich führe ich noch einen paar Pings aus

root@ubuntu-1gb-fra1-01:~# ping -c 8 10.10.209.87
PING 10.10.209.87 (10.10.209.87) 56(84) bytes of data.
64 bytes from 10.10.209.87: icmp_seq=1 ttl=64 time=1.64 ms
64 bytes from 10.10.209.87: icmp_seq=2 ttl=64 time=0.719 ms
64 bytes from 10.10.209.87: icmp_seq=3 ttl=64 time=0.444 ms
64 bytes from 10.10.209.87: icmp_seq=4 ttl=64 time=0.428 ms
64 bytes from 10.10.209.87: icmp_seq=5 ttl=64 time=0.427 ms
64 bytes from 10.10.209.87: icmp_seq=6 ttl=64 time=0.399 ms
64 bytes from 10.10.209.87: icmp_seq=7 ttl=64 time=0.423 ms
64 bytes from 10.10.209.87: icmp_seq=8 ttl=64 time=0.500 ms

--- 10.10.209.87 ping statistics ---
8 packets transmitted, 8 received, 0% packet loss, time 7003ms
rtt min/avg/max/mdev = 0.399/0.623/1.647/0.399 ms

Latenz erhöhen

Wie zu erwarten, ist die Latenz und die Übertragungsrate aktuell perfekt. Das ändern wir jetzt.

Wir fangen dazu einmal klein an, und setzen eine Latenz von 100ms

tc qdisc add dev eth0 root netem delay 100ms

Nun wiederholen wir unseren wget Test und die Pings

root@ubuntu-1gb-fra1-01:~# wget http://10.10.209.87/250mb.test
--2017-08-16 18:52:14--  http://10.10.209.87/250mb.test
Connecting to 10.10.209.87:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 262144000 (250M)
Saving to: ‘250mb.test’

250mb.test      100%[===========================>] 250.00M  27.5MB/s    in 18s

2017-08-16 18:52:33 (13.5 MB/s) - ‘250mb.test’ saved [262144000/262144000]
root@ubuntu-1gb-fra1-01:~# ping -c 8 10.10.209.87
PING 10.10.209.87 (10.10.209.87) 56(84) bytes of data.
64 bytes from 10.10.209.87: icmp_seq=1 ttl=64 time=102 ms
64 bytes from 10.10.209.87: icmp_seq=2 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=3 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=4 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=5 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=6 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=7 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=8 ttl=64 time=100 ms

--- 10.10.209.87 ping statistics ---
8 packets transmitted, 8 received, 0% packet loss, time 7012ms
rtt min/avg/max/mdev = 100.423/100.797/102.240/0.647 ms

Wie man schön erkennen kann, ist die Downloadrate von 89MB/s auf 13,5MB/s gefallen und der Download der 250MB hat fast doppelt solange gedauert.

Auch die Ping Zeiten liegen nun immer ≥100ms.

Package Loss hinzufügen

Um die Lange noch zu verschlimmern, fügen wir noch etwas Package Loss hinzu. Damit müsst ihr etwas vorsichtig sein, besonders wenn ihr wie ich, über SSH auf das System zugreift! Ich setze bei mir einmal einen Wert von 20% bei 100ms Latenz.

tc qdisc change dev eth0 root netem loss 10% delay 100ms

Ok 20% war dann wohl doch etwas zu viel... Ich habe den wget Test bei mir abgebrochen weil ich keine Stunde warten wollte.

root@ubuntu-1gb-fra1-01:~# wget http://10.10.209.87/250mb.test
--2017-08-16 18:58:41--  http://10.10.209.87/250mb.test
Connecting to 10.10.209.87:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 262144000 (250M)
Saving to: ‘250mb.test’

250mb.test      3%[===>                          ]   8.59M  57.1KB/s    eta 59m 55s
^C

Im Ergebnis von Ping sieht man jedoch schön, was ich da angerichtet habe.

root@ubuntu-1gb-fra1-01:~# ping -c 10 10.10.209.87
PING 10.10.209.87 (10.10.209.87) 56(84) bytes of data.
64 bytes from 10.10.209.87: icmp_seq=1 ttl=64 time=101 ms
64 bytes from 10.10.209.87: icmp_seq=2 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=4 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=5 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=6 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=7 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=8 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=9 ttl=64 time=101 ms
64 bytes from 10.10.209.87: icmp_seq=10 ttl=64 time=100 ms

--- 10.10.209.87 ping statistics ---
10 packets transmitted, 9 received, 10% packet loss, time 9020ms
rtt min/avg/max/mdev = 100.430/100.720/101.765/0.527 ms

Ich habe 10 Pings abgeschickt, deshalb genau 10% Package Loss.

Ok, also weg mit dem Package Loss

tc qdisc del dev eth0 root netem loss 10% delay 100ms

Bandbreite einschränken

Je nachdem wo unsere Systeme stehen, habe diese eventuell nicht immer die beste Bandbreite zur Verfügung, ein gutes Beispiel ist der Upload am heimischen DSL Anschluss.

Ich setze also wieder eine Latenz von 100ms und beschränke die Bandbreite auf 200kbit/s

tc qdisc add dev eth0 root netem delay 100ms rate 2000kbit
root@ubuntu-1gb-fra1-01:~# wget http://10.10.209.87/250mb.test
--2017-08-16 19:17:24--  http://10.10.209.87/250mb.test
Connecting to 10.10.209.87:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 262144000 (250M)
Saving to: ‘250mb.test’

250mb.test      3%[===>                          ]   8.53M   233KB/s    eta 17m 41s
^C

Auch in diesem Fall hatte ich keine Lust, 18 Minuten auf wget zu warten. Man sieht allerdings gut, das die Rate bei 233KB/s liegt.

Einen Ping stört dies natürlich nicht weiter

root@ubuntu-1gb-fra1-01:~# ping -c 10 10.10.209.87
PING 10.10.209.87 (10.10.209.87) 56(84) bytes of data.
64 bytes from 10.10.209.87: icmp_seq=1 ttl=64 time=102 ms
64 bytes from 10.10.209.87: icmp_seq=2 ttl=64 time=101 ms
64 bytes from 10.10.209.87: icmp_seq=3 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=4 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=5 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=6 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=7 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=8 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=9 ttl=64 time=100 ms
64 bytes from 10.10.209.87: icmp_seq=10 ttl=64 time=101 ms

--- 10.10.209.87 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9014ms
rtt min/avg/max/mdev = 100.776/101.065/102.247/0.598 ms

Experimentieren

Mit all diesen Werten muss man natürlich etwas experimentieren und spielen. Dabei muss dann immer die Performance der Applikation überwacht werden.

Wichtig ist auch, zu wissen was man möchte. Es macht nicht wirklich Sinn, die Applikation auf hohe Latenzen oder Package Loss zu optimiert, wenn dies in der Praxis nicht auftritt, weil alle Server im gleichen Rack hängen. Auch ist es nicht immer eine gute Idee, Cluster über mehrere Standorte zu verteilen.

Bitte vergesst nicht, die Einstellungen wieder zu löschen

tc qdisc del dev eth0 root netem delay 100ms rate 2000kbit

Ich habe das bei mir zur Sicherheit noch einmal mit wget überprüft

root@ubuntu-1gb-fra1-01:~# wget http://10.10.209.87/250mb.test
--2017-08-16 19:28:10--  http://10.10.209.87/250mb.test
Connecting to 10.10.209.87:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 262144000 (250M)
Saving to: ‘250mb.test’

250mb.test      100%[===========================>] 250.00M   171MB/s    in 1.5s

2017-08-16 19:28:12 (171 MB/s) - ‘250mb.test’ saved [262144000/262144000]