Genauigkeit bei Performance-Tests mit `wrk`

API7.ai

November 25, 2022

OpenResty (NGINX + Lua)

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 der off 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.