Genauigkeit bei Performance-Tests mit `wrk`
API7.ai
November 25, 2022
In diesem Artikel werden wir über Leistungstests sprechen. Dieser Teil ist nicht spezifisch für OpenResty, sondern gilt auch für andere Backend-Dienste.
Leistungstests sind weit verbreitet, und wenn wir Produkte ausliefern, werden sie alle mit Leistungskennzahlen geliefert, wie z.B. QPS, TPS, Latenz, die Anzahl der Benutzer, die gleichzeitig unterstützt werden, und so weiter. Für Open-Source-Projekte führen wir auch vor der Veröffentlichung einer Version einen Leistungstest durch, um ihn mit der vorherigen Version zu vergleichen und festzustellen, ob es einen signifikanten Rückgang gibt. Es gibt auch neutrale Websites, die vergleichende Leistungsdaten ähnlicher Produkte veröffentlichen. Ich muss sagen, dass Leistungstests uns sehr nahe sind.
Wie führt man also wissenschaftliche und rigorose Leistungstests durch?
Leistungstest-Tools
Um eine gute Arbeit zu leisten, muss man zunächst ein gutes Werkzeug verwenden. Die Wahl eines guten Leistungstest-Tools ist der halbe Erfolg.
Das Apache Benchmark-Tool, auch bekannt als ab
, das Ihnen bekannt sein sollte, ist wohl das einfachste Leistungstest-Tool, aber leider ist es nicht sehr nützlich. Dies liegt daran, dass die aktuelle Serverseite auf gleichzeitiger und asynchroner I/O basiert, deren Leistung nicht schlecht ist. Das ab
nutzt die Mehrkernfähigkeiten der Maschine nicht aus, und die generierten Anfragen stehen nicht unter ausreichendem Druck. In diesem Fall sind die Ergebnisse, die man mit ab
erhält, nicht real.
Daher können wir ein Kriterium für das Belastungstest-Tool wählen: Das Tool selbst hat eine solide Leistung und kann genügend Druck erzeugen, um das Serverprogramm zu belasten.
Natürlich können Sie auch mehr Geld ausgeben, um viele Belastungstest-Clients zu starten und sie in ein verteiltes Belastungstestsystem zu verwandeln. Aber vergessen Sie nicht, dass die Komplexität dadurch ebenfalls steigt.
Zurück zur OpenResty-Praxis: Unser empfohlenes Leistungstest-Tool ist wrk
. Warum wählen wir es?
Erstens erfüllt wrk
die Kriterien für die Tool-Auswahl. Der von wrk
auf einer einzelnen Maschine erzeugte Druck kann NGINX leicht dazu bringen, 100 % CPU-Auslastung zu erreichen, ganz zu schweigen von anderen Serveranwendungen.
Zweitens hat wrk
viele Gemeinsamkeiten mit OpenResty. wrk
ist kein Open-Source-Projekt, das von Grund auf neu geschrieben wurde; es steht auf den Schultern von LuaJIT und Redis und nutzt die Mehrkernressourcen des Systems, um Anfragen zu generieren. Darüber hinaus bietet wrk
eine Lua-API, die es Ihnen ermöglicht, Ihre eigenen Lua-Skripte einzubetten, um Anfrageheader und -inhalte anzupassen, was es sehr flexibel macht.
Wie sollten wir also wrk
verwenden? Es ist so einfach wie das Betrachten des folgenden Code-Snippets.
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html
Dies bedeutet, dass wrk
12 Threads verwendet, 400 langlaufende Verbindungen für 30 Sekunden hält, um HTTP-Anfragen an die angegebene API-Schnittstelle zu senden. Natürlich, wenn Sie keine Parameter angeben, startet wrk
standardmäßig zwei Threads und zehn langlaufende Verbindungen.
Testumgebung
Nachdem wir die Testtools gefunden haben, können wir den Belastungstest nicht direkt starten. Wir müssen die Testumgebung einmal überprüfen. Es gibt vier Hauptpunkte, die in der Testumgebung überprüft werden müssen, und ich werde sie im Detail besprechen.
1. SELinux deaktivieren
Wenn Sie ein CentOS/RedHat-Betriebssystem haben, wird empfohlen, SELinux zu deaktivieren. Andernfalls könnten Sie auf viele seltsame Berechtigungsprobleme stoßen.
Lassen Sie uns überprüfen, ob SELinux aktiviert ist, mit dem folgenden Befehl.
$ sestatus
SELinux status: disabled
Wenn es aktiviert ist (enforcing), können Sie es vorübergehend mit $ setenforce 0
deaktivieren; ändern Sie auch die Datei /etc/selinux/config
, um es dauerhaft zu deaktivieren, indem Sie SELINUX=enforcing
in SELINUX=disabled
ändern.
2. Maximale Anzahl offener Dateien
Dann müssen Sie die maximale Anzahl offener Dateien des aktuellen Systems mit dem folgenden Befehl überprüfen.
$ cat /proc/sys/fs/file-nr
3984 0 3255296
Die letzte Zahl 3255296
hier ist die maximale Anzahl offener Dateien. Wenn diese Zahl auf Ihrer Maschine klein ist, müssen Sie die Datei /etc/sysctl.conf
ändern, um sie zu erhöhen.
fs.file-max = 1020000
net.ipv4.ip_conntrack_max = 1020000
net.ipv4.netfilter.ip_conntrack_max = 1020000
Nach der Änderung müssen Sie den Systemdienst neu starten, damit die Änderungen wirksam werden.
sudo sysctl -p /etc/sysctl.conf
3. Prozesslimits
Neben der maximalen Anzahl offener Dateien auf dem System gibt es auch eine Begrenzung der Anzahl der Dateien, die ein Prozess öffnen kann, die Sie mit dem Befehl ulimit
überprüfen können.
$ ulimit -n
1024
Sie werden feststellen, dass dieser Wert standardmäßig 1024 beträgt, ein kleiner Wert. Da jede Benutzeranfrage einem Dateihandle entspricht und Belastungstests viele Anfragen generieren, müssen wir diesen Wert erhöhen und ihn auf Millionen ändern, was Sie vorübergehend mit dem folgenden Befehl tun können.
ulimit -n 1024000
Sie können auch die Konfigurationsdatei /etc/security/limits.conf
ändern, um dies dauerhaft zu machen.
* hard nofile 1024000
* soft nofile 1024000
4. NGINX-Konfiguration
Schließlich müssen Sie eine kleine Änderung an der NGINX-Konfiguration vornehmen, und zwar die folgenden drei Codezeilen.
events {
worker_connections 10240;
}
Dies ermöglicht es uns, die Anzahl der Verbindungen pro Worker zu erhöhen. Da der Standardwert nur 512 beträgt, reicht dies für Hochlasttests nicht aus.
Überprüfung vor dem Belastungstest
An diesem Punkt ist die Testumgebung bereit. Sie sind sicher gespannt, loszulegen und es zu testen, oder? Lassen Sie uns ein letztes Mal überprüfen, bevor wir den Test mit wrk
starten. Schließlich machen Menschen Fehler, daher ist es wichtig, einen Kreuztest durchzuführen.
Dieser letzte Test kann in zwei Schritte unterteilt werden.
1. Verwenden Sie das automatisierte Tool c1000k
c1000k stammt vom Autor von SSDB
. Wie Sie am Namen erkennen können, besteht der Zweck dieses Tools darin, zu überprüfen, ob Ihre Umgebung die Anforderungen von 10^6 gleichzeitigen Verbindungen erfüllen kann.
Die Verwendung dieses Tools ist ebenfalls unkompliziert. Wir starten einen server
und einen client
, entsprechend dem Serverprogramm, das auf Port 7000
lauscht, und dem Clientprogramm, das den Belastungstest startet, um den Belastungstest in einer realen Umgebung zu simulieren:
. /server 7000
. /client 127.0.0.1 7000
Unmittelbar danach sendet der client
eine Anfrage an den server
, um zu überprüfen, ob die aktuelle Systemumgebung eine Million gleichzeitige Verbindungen unterstützen kann. Sie können es selbst ausführen und das Ergebnis sehen.
2. Überprüfen Sie, ob das Serverprogramm normal läuft
Wenn das Serverprogramm nicht korrekt funktioniert, könnte der Belastungstest zu einem Test der Fehlerprotokollaktualisierung oder zu einem 404
-Antworttest werden.
Daher ist der letzte und wichtigste Schritt der Testumgebungsprüfung, den Unit-Test-Satz des Servers durchzulaufen oder manuell einige wichtige Schnittstellen aufzurufen, um sicherzustellen, dass alle Schnittstellen, Rückgaben und HTTP-Antwortcodes des wrk
-Tests normal sind und dass es keine Fehlermeldungen in logs/error.log
gibt.
Anfragen senden
Okay, jetzt ist alles bereit. Lassen Sie uns mit wrk
den Belastungstest starten!
$ wrk -d 30 http://127.0.0.2:9080/hello
Running 30s test @ http://127.0.0.2:9080/hello
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 595.39us 178.51us 22.24ms 90.63%
Req/Sec 8.33k 642.91 9.46k 59.80%
499149 requests in 30.10s, 124.22MB read
Requests/sec: 16582.76
Transfer/sec: 4.13MB
Ich habe hier keine Parameter angegeben, sodass wrk
standardmäßig 2 Threads und 10 langlaufende Verbindungen startet. Sie müssen die Anzahl der Threads und Verbindungen in wrk
nicht sehr groß einstellen; solange Sie das Zielprogramm dazu bringen können, 100 % CPU-Auslastung zu erreichen, ist alles in Ordnung.
Aber die Dauer des Belastungstests darf nicht zu kurz sein, da ein Belastungstest von ein paar Sekunden bedeutungslos ist. Andernfalls ist der Belastungstest wahrscheinlich beendet, bevor das Serverprogramm das Hot-Reloading abgeschlossen hat. Gleichzeitig müssen Sie ein Überwachungstool wie top
oder htop
verwenden, um zu überprüfen, ob das Zielprogramm auf dem Server während des Belastungstests 100 % CPU-Auslastung erreicht.
Phänomenal, wenn die CPU voll ausgelastet ist und die CPU- und Speichernutzung nach Beendigung des Tests schnell abnimmt, dann herzlichen Glückwunsch, der Test wurde erfolgreich abgeschlossen. Wenn jedoch Ausnahmen wie die folgenden auftreten, sollten Sie als Serverentwickler darauf achten.
- Die CPU kann nicht voll ausgelastet werden. Dies ist kein
wrk
-Problem; es könnte eine Netzwerkbeschränkung oder eine blockierende Operation in Ihrem Code sein. Sie können dies durch Überprüfen Ihres Codes oder durch Verwendung deroff CPU
-Flammengrafik feststellen. - Die CPU ist immer voll ausgelastet, auch wenn der Belastungstest gestoppt wird. Dies deutet auf eine Endlosschleife im Code hin, die durch einen regulären Ausdruck oder einen LuaJIT-Bug verursacht wird, was ich in realen Umgebungen erlebt habe. In diesem Fall müssen Sie die CPU-Flammengrafik verwenden, um dies zu bestimmen.
Schließlich werfen wir einen Blick auf die wrk
-Statistiken. In Bezug auf dieses Ergebnis konzentrieren wir uns im Allgemeinen auf zwei Werte.
Der erste ist QPS, oder Requests/sec: 16582.76
, was eine genaue Zahl ist, die angibt, wie viele Anfragen pro Sekunde auf der Serverseite verarbeitet werden.
Der zweite ist die Latenz: Latency 595.39us 178.51us 22.24ms 90.63%
, die genauso wichtig ist wie QPS und die Reaktionsgeschwindigkeit des Systems widerspiegelt. Zum Beispiel möchten wir bei Gateway-Anwendungen die Latenz innerhalb von 1 ms halten.
Darüber hinaus bietet wrk
auch einen latency
-Parameter, der die prozentuale Verteilung der Latenz detailliert ausgibt, zum Beispiel.
Latency Distribution
50% 134.00us
75% 180.00us
90% 247.00us
99% 552.00us
Allerdings sind die Latenzverteilungsdaten von wrk
ungenau, da sie künstlich Netzwerk- und Tool-Störungen hinzufügen, die die Latenz verstärken, was Ihre besondere Aufmerksamkeit erfordert.
Zusammenfassung
Leistungstests sind eine technische Aufgabe; nicht viele Menschen können sie richtig und gut durchführen. Ich hoffe, dieser Artikel gibt Ihnen ein umfassenderes Verständnis von Leistungstests.
Zum Schluss stelle ich Ihnen eine Frage: wrk
unterstützt benutzerdefinierte Lua-Skripte für Belastungstests. Können Sie also basierend auf seiner Dokumentation ein einfaches Lua-Skript schreiben? Es könnte ein bisschen schwierig sein, aber Sie werden die Absicht der von wrk
bereitgestellten Schnittstellen verstehen, wenn Sie es fertiggestellt haben.
Sie sind herzlich eingeladen, diesen Artikel mit mehr Menschen zu teilen, und wir werden gemeinsam Fortschritte machen.