Ich führe eine Reihe von Auslastungstests durch, um die Leistung des folgenden Setups zu bestimmen:
Node.js test suite (client) --> StatsD (server) --> Graphite (server)
Kurz gesagt, die Testsuite node.js sendet alle x Sekunden eine festgelegte Anzahl von Metriken an eine StatsD-Instanz, die sich auf einem anderen Server befindet. StatsD spült dann die Metriken im Sekundentakt zu einer Graphite-Instanz, die sich auf demselben Server befindet. Ich schaue dann nach, wie viele Metriken tatsächlich von der Testsuite gesendet und wie viele von Graphite empfangen wurden, um den Paketverlust zwischen der Testsuite und Graphite zu bestimmen.
Ich bemerkte jedoch, dass ich manchmal sehr hohe Paket-Drop-Raten bekam (beachten Sie, dass es mit dem UDP-Protokoll gesendet wird), die zwischen 20 und 50% lagen. Zu diesem Zeitpunkt begann ich zu untersuchen, wo diese Pakete abgelegt wurden, da es sich um ein Leistungsproblem bei StatsD handeln könnte. Also begann ich, die Metriken in jedem Teil des Systems zu protokollieren, um herauszufinden, wo dieser Abfall auftrat. Und hier wird es komisch.
Ich verwende tcpdump , um eine Erfassungsdatei zu erstellen, die ich nach Abschluss des Tests überprüfe. Aber wenn ich die Tests mit laufendem tcpdump durchführe, ist der Paketverlust fast nicht vorhanden! Es sieht so aus, als würde tcpdump die Leistung meiner Tests irgendwie steigern, und ich kann nicht herausfinden, warum und wie dies geschieht. Ich führe den folgenden Befehl aus, um die tcpdump-Nachrichten sowohl auf dem Server als auch auf dem Client zu protokollieren:
tcpdump -i any -n port 8125 -w test.cap
In einem bestimmten Testfall sende ich 40000 Metriken / s. Der Test unter tcpdump hat einen Paketverlust von ca. 4%, während der Test ohne tcpdump einen Paketverlust von ca. 20% hat.
Beide Systeme werden als Xen-VMs mit folgendem Setup ausgeführt:
- Intel Xeon E5-2630 v2 bei 2,60 GHz
- 2 GB RAM
- Ubuntu 14.04 x86_64
Dinge, die ich bereits auf mögliche Ursachen überprüft habe:
- Erhöhen der Empfangs- / Sendegröße des UDP-Puffers.
- CPU-Auslastung wirkt sich auf den Test aus. (maximale Auslastung von 40-50%, sowohl Client- als auch Serverseite)
- Ausführen von tcpdump auf bestimmten Schnittstellen anstelle von "any".
- Ausführen von tcpdump mit '-p', um den Promiscuous-Modus zu deaktivieren.
- Ausführen von tcpdump nur auf dem Server. Dies führte zu einem Paketverlust von 20% und schien die Tests nicht zu beeinträchtigen.
- Ausführen von tcpdump nur auf dem Client. Dies führte zu einer Leistungssteigerung.
- Erhöhen von netdev_max_backlog und netdev_budget auf 2 ^ 32-1. Das machte keinen Unterschied.
- Versuchte jede mögliche Einstellung des Promiscuous-Modus auf jedem NIC (Server an und Client aus, Server aus und Client an, beide an, beide aus). Das machte keinen Unterschied.
-p
Option überspringen, um festzustellen, ob dies einen Unterschied macht.ifconfig eth0 promisc
undifconfig eth0 -promisc
deaktiviert den Promiscuous-Modus auf eth0. Wenn es einen Unterschied macht, vergleichen Sie die 4 möglichen Kombinationen von Promisc-Ein / Aus auf beiden Computern. Dies könnte helfen, die Ursache der Probleme zu lokalisieren.Antworten:
Wenn tcpdump ausgeführt wird, werden die eingehenden Frames ziemlich schnell eingelesen. Meine Hypothese ist, dass die Paketringpuffereinstellungen der Netzwerkkarte möglicherweise etwas zu klein sind. Wenn tcpdump ausgeführt wird, wird es schneller geleert.
Wenn Sie ein Red Hat-Abonnent sind, ist dieser Support-Artikel eine sehr nützliche Übersicht über den Paketempfang . Es sind einige Dinge drin, über die Sie, glaube ich, noch nicht nachgedacht haben.
Überlegen Sie, wie Ihr System mit IRQs umgeht. Ziehen Sie in Betracht, das 'dev_weight' der Netzwerkschnittstelle zu erhöhen (was bedeutet, dass mehr Pakete von der Netzwerkkarte in den Benutzerraum gelesen werden). Überprüfen Sie, wie oft die Anwendung den Socket liest (kann sie einen dedizierten Thread verwenden, sind Probleme / Problemumgehungen hinsichtlich der Skalierbarkeit bekannt?).
Erhöhen Sie den NIC-Frame-Puffer (verwenden Sie den
ethtool
Befehl - sehen Sie sich die--set-ring
Argumente usw. an).Schauen Sie sich 'Receive Side Scaling' an und verwenden Sie mindestens so viele Empfangsthreads, um den Datenverkehr einzulesen.
Ich frage mich, ob tcpdump etwas cooles macht, wie die Kernelunterstützung für Paketringpuffer . Das würde helfen, das Verhalten zu erklären, das Sie sehen.
quelle
Welchen Power Governor verwenden Sie? Ich habe ähnliche Verhaltensweisen mit "ondemand" oder "konservativem" Gouverneur gesehen.
Versuchen Sie, den "Leistungsregler" zu verwenden und alle Energiesparfunktionen im Server-BIOS zu deaktivieren.
Ändert es etwas?
quelle
cpufreq-info
, bekomme aber eine Nachrichtno or unknown cpufreq driver is active on this CPU
. Auch bei Benutzungcpupower frequency-info
kehrt es zurückno or unknown cpufreq driver is active on this CPU
. Obwohl ich dies im Moment nicht bestätigen kann , glaube ich auf der Website des VM-Herstellers , dass es im "Performance" -Modus läuft, da ich eine Intel-CPU habe.cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
2)cat /proc/cpuinfo
3)lsmod | grep cpu
Ein anderer Weg ist das
ip_conntarck
Modul. Sind Sie sicher, dass Ihre Linux-Box eine neue Verbindung akzeptieren kann? Test über:Du musst testen
Wenn max == count ist, ist Ihre maximale Verbindung voll und Ihre Linux-Box kann keine neue Verbindung akzeptieren.
Wenn Sie ip_conntrack nicht haben, können Sie es einfach über laden
modprobe ip_conntrack
quelle
Ich vermute, die empfangende Seite ist einfach nicht in der Lage, die Paketrate zu handhaben, und hier ist der Grund:
Durch die Verwendung von tcpdump auf dem Client werden die verworfenen Pakete reduziert: tcpdump verlangsamt den Client, und daher sieht der Server eine viel niedrigere Packer-Rate, die er teilweise noch verarbeiten kann. Sie sollten in der Lage sein, diese Hypothese zu bestätigen, indem Sie die RX / TX-Paketzähler sowohl auf dem Client als auch auf dem Server überprüfen
Sie haben erwähnt, dass Sie die Empfangs- / Sendegröße des UDP-Puffers erhöht haben. Können Sie genauer erläutern, wie? Es ist wichtig, dass Sie auf dem Server sowohl rmem_max als auch rmem_default ändern. Beispiel:
sysctl -w net.core.rmem_max=524287 sysctl -w net.core.wmem_max=524287 sysctl -w net.core.rmem_default=524287 sysctl -w net.core.wmem_default=524287
Testen Sie Ihre Einstellungen
Stoppen Sie statsd und die Node-Anwendung, und testen Sie im Leerlauf des Systems mit iperf die Paketrate , die das Netzwerk / der Kernel verarbeiten kann. Wenn Sie 40K-Pakete / s mit iperf streamen können, aber nicht mit statsd, sollten Sie sich auf die Optimierung von statsd konzentrieren.
Andere Tunables
Denken Sie auch daran, net.core.netdev_max_backlog zu optimieren : Maximale Anzahl von Paketen, die in die Warteschlange gestellt werden dürfen, wenn eine bestimmte Schnittstelle Pakete schneller empfängt, als der Kernel sie verarbeiten kann.
quelle