
Ich führe eine Reihe von Belastungstests durch, um die Leistung des folgenden Setups zu ermitteln:
Node.js test suite (client) --> StatsD (server) --> Graphite (server)
Kurz gesagt sendet die Testsuite von node.js alle x Sekunden eine festgelegte Anzahl von Metriken an eine StatsD-Instanz, die sich auf einem anderen Server befindet. StatsD überträgt die Metriken dann wiederum jede Sekunde an eine Graphite-Instanz, die sich auf demselben Server befindet. Ich schaue mir dann an, 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.
Mir fiel jedoch auf, dass ich manchmal sehr hohe Paketverlustraten hatte (beachten Sie, dass die Pakete mit dem UDP-Protokoll gesendet werden), die zwischen 20 und 50 % lagen. Also begann ich zu untersuchen, wo diese Pakete verloren gingen, da es sich um ein Leistungsproblem mit StatsD handeln könnte. Also begann ich, die Metriken in jedem Teil des Systems zu protokollieren, um herauszufinden, wo dieser Verlust auftrat. Und hier wird es seltsam.
Ich benutzetcpdumpum eine Capture-Datei zu erstellen, die ich nach Abschluss des Tests überprüfe. Aber wenn ich die Tests mit laufendem tcpdump durchführe, gibt es fast keinen Paketverlust! Es sieht so aus, als würde tcpdump die Leistung meiner Tests irgendwie steigern, und ich kann nicht herausfinden, warum und wie das passiert. 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 mit laufendem tcpdump hat einen Paketverlust von etwa 4 %, während der Test ohne tcpdump einen Paketverlust von etwa 20 % hat
Beide Systeme laufen als Xen-VMs mit folgendem Setup:
- Intel Xeon E5-2630 v2 @ 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, die den Test beeinflusst. (max. Auslastung von 40–50 %, sowohl client- als auch serverseitig)
- Ausführen von tcpdump auf bestimmten Schnittstellen statt auf „beliebigen“.
- 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 scheint 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. Dies machte keinen Unterschied.
- Habe jede mögliche Einstellung des Promiscuous-Modus auf jeder Netzwerkkarte ausprobiert (Server an und Client aus, Server aus und Client an, beide an, beide aus). Es hat keinen Unterschied gemacht.
Antwort1
Wenn tcpdump läuft, liest es die eingehenden Frames relativ schnell ein. Meine Hypothese ist, dass die Paketringpuffereinstellungen der Netzwerkkarte möglicherweise etwas zu klein sind; wenn tcpdump läuft, wird er schneller geleert.
Wenn Sie Red Hat-Abonnent sind, ist dieser Support-Artikel sehr nützlichÜbersicht über den Paketempfang. Da stehen ein paar Dinge drin, die Sie, glaube ich, noch nicht bedacht haben.
Bedenken Sie, wie Ihr System mit IRQs umgeht. Erwägen Sie eine Erhöhung des „dev_weight“ der Netzwerkschnittstelle (was bedeutet, dass mehr Pakete von der Netzwerkkarte in den Benutzerbereich gelesen werden). Sehen Sie sich an, wie häufig die Anwendung den Socket liest (kann sie einen dedizierten Thread verwenden, gibt es bekannte Probleme/Workarounds hinsichtlich der Skalierbarkeit).
Erhöhen Sie den NIC-Frame-Puffer (mit dem ethtool
Befehl – beachten Sie die --set-ring
Argumente usw.).
Sehen Sie sich die „Skalierung auf der Empfangsseite“ an und verwenden Sie mindestens so viele Empfangs-Threads, um den Datenverkehr einzulesen.
Ich frage mich, ob tcpdump etwas Cooles macht, wie zum Beispiel die Nutzung der Kernel-Unterstützung fürPaketringpuffer. Das würde helfen, das Verhalten zu erklären, das Sie beobachten.
Antwort2
Welchen Leistungsregler verwenden Sie? Ich habe ähnliche Verhaltensweisen mit einem „On-Demand“- oder „Conservative“-Regler gesehen.
Versuchen Sie, den Leistungsregler zu verwenden und alle Energiesparfunktionen im Server-BIOS zu deaktivieren.
Ändert es etwas?
Antwort3
Eine andere Möglichkeit ist ip_conntarck
ein Modul. Sind Sie sicher, dass Ihre Linux-Box eine neue Verbindung akzeptieren kann? Testen Sie es über:
root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_max
net.ipv4.netfilter.ip_conntrack_max = 65536
root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 29
Sie müssen testen
net.ipv4.netfilter.ip_conntrack_max > net.ipv4.netfilter.ip_conntrack_count
wenn max == count , ist Ihre maximale Verbindung ausgeschöpft und Ihre Linux-Box kann keine neue Verbindung annehmen.
Wenn Sie ip_conntrack nicht haben, können Sie einfach laden übermodprobe ip_conntrack
Antwort4
Ich vermute, dass die Empfangsseite einfach nicht in der Lage ist, die Paketrate zu bewältigen, und zwar aus folgendem Grund:
Verwenden von tcpdumpauf dem Clientreduziert die Anzahl verlorener Pakete: tcpdump verlangsamt den Client und daher sieht der Server eine viel niedrigere Packerrate, die er teilweise noch verarbeiten kann. Sie sollten diese Hypothese bestätigen können, 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 im Detail erläutern, wie? Es ist wichtig, dass Sie auf dem Server sowohl rmem_max ändernUndrmem_default, 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 Ihrer Einstellungen
Stoppen Sie statsd und die Knotenanwendung, dann mit dem System im Leerlauf verwendeniperfum die Paketrate zu testen, die das Netzwerk/der Kernel verarbeiten kann. Wenn Sie mit iperf 40.000 Pakete/s streamen können, mit statsd aber nicht, sollten Sie sich auf die Feinabstimmung von statsd konzentrieren.
Andere einstellbare Werte
Denken Sie auch daran,net.core.netdev_max_backlog: 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.