[PYTHON] Webserver als Ersatz für Apache: uWSGI-Leistungsoptimierung

Hintergrund

Ich entwickle einen Anwendungsserver für einige Telefonspiele mit Python und Django und verwende uWSGI als Webserver. uWSGI hat zu viele Parameter und es ist schwierig zu wissen, welche man wählen soll.

Ich habe tatsächlich einen Belastungstest durchgeführt, verschiedene Parameter geändert und jetzt kann ich eine stabile Leistung erzielen. Ich möchte mitteilen, wie ich es damals gemessen habe und welche Parameter ich geändert habe.

Umgebung

server.png

Leistungsmesswerkzeug

"Nicht raten, messen"

Es gibt ein Wort, aber wenn Sie es nicht messen können, wissen Sie nicht, ob es sich verbessert hat. Die folgenden Tools waren diesmal hauptsächlich nützlich.

Über uwsgitop

Leistungsstatistikdaten können wie folgt in den Einstellungen auf der uWSGI-Seite an den Socket ausgegeben werden.

stats = /var/run/uWSGI/projectname.stats.sock
memory-report = true

Wenn Sie uWSGI top wie folgt mit pip usw. ausführen, können Sie die Statistiken in Echtzeit wie den Unix-Befehl top anzeigen.

$ uwsgitop /var/run/uWSGI/projectname.stats.sock

Das Folgende ist ein Ausführungsbeispiel. In diesem Zustand handelt es sich um eine Prozesseinheit. Wenn Sie jedoch eine Taste auf der Tastatur drücken, können Sie sie auch in einer Thread-Einheit anzeigen.

uwsgitop.png

Diesmal werden UWSGI-Einstellungen festgelegt, die für die Leistungsoptimierung wirksam sind

uWSGI-Optionen enthält Werte für verschiedene Einstellungsdateien, es sind jedoch zu viele Einstellungen zum Festlegen vorhanden. Es ist zunächst schwer zu wissen, ob Sie es schaffen. Darüber hinaus ist die Erklärung der Optionen einfach, und der Autor von uWSGI selbst bittet Sie, sich die Quelle anzusehen. Daher ist es schwierig, wenn Sie sie noch nie verwendet haben.

Hier möchte ich die Parameter erhöhen, die wirksam waren, als ich sie tatsächlich einstellte.

processes, threads

uWSGI kann die Anzahl der Prozesse und Threads angeben, die Anforderungen akzeptieren. Das von uns entwickelte uWSGI hat die folgenden Einstellungen.

processes = 16
threads = 1

Ich habe es mit verschiedenen Kombinationen von Prozessen und Threads getestet, aber als ich die Anzahl der Threads erhöhte, erhöhte sich die Anzahl der Kontextwechsel und der behandelte RPS betrug weniger als die Hälfte.

vmstat_1.png


vmstat_2.png

Übrigens, wenn Threads 1 ist, gibt es keinen großen Unterschied, selbst wenn Prozesse erhöht werden, wenn die Anzahl der Kerne 8 oder mehr beträgt.

thunder-lock

Wenn Sie einen Linux-Server verwenden, sollten Sie diese Option zunächst wie unten gezeigt auf true setzen.

thunder-lock = true

Weitere Informationen finden Sie unter hier. Wenn dies jedoch falsch ist, handelt es sich um eine Anforderung zur Verarbeitung in mehreren uWSGI-Prozessen. Wird voreingenommen sein.

uwsgitop_1.png


uwsgitop_2.png

max-requests, max-requests-delta

max-request ist eine Einstellung für die Anzahl der Anforderungen, die der Prozess vor dem erneuten Laden erhält. Es wird wie folgt eingestellt.

max-requests = 6000

Zu Beginn des Auslastungstests war dieser Wert ein großer Wert, er wurde nicht neu geladen und der Status der Speichernutzung war wie folgt.

memory_1.png

Wenn ich mir anschaue, wie der Speicher des uWSGI-Prozesses zunimmt, ist 6000 angemessen, also habe ich es so eingestellt. Ich denke, es ist notwendig zu untersuchen, warum der Speicher zunimmt, aber da er alle 6000 Mal neu geladen wird, wird beurteilt, dass es keinen Effekt gibt und er eingestellt ist. Beim erneuten Laden wird der Speicher freigegeben und befindet sich in demselben Zustand wie beim ersten Start.

Ich habe vergessen, jeden Vorgang auszuführen, aber wenn er richtig eingestellt ist, wird sich der Speicher in einem bestimmten Zeitraum wie unten gezeigt beruhigen.

memory_2.png

Beachten Sie hier jedoch, dass der Prozess beim Neustart einige Sekunden lang keine neuen Anforderungen empfangen kann. Wenn Sie auf alle Prozesse den gleichen Wert für max-Anfragen anwenden, werden diese fast alle gleichzeitig neu gestartet, und der gesamte Server empfängt einige Sekunden lang keine Anfragen.

Um dies zu vermeiden, wird der Wert max-request-delta wie folgt eingestellt.

max-requests-delta = 300

Es wird mit diesem Unterschied für jeden Prozess neu gestartet. Wenn beispielsweise ein Prozess bei 6000 neu gestartet wird, wird der nächste Prozess neu gestartet, wenn 6300 Anforderungen empfangen werden. Unter der Annahme, dass der RPS ungefähr 16 beträgt und der Prozess auf 16 gesetzt ist, empfängt ein Prozess jede Sekunde eine Anforderung, sodass er alle 300 Sekunden neu gestartet wird. Auf diese Weise wird der Prozess des gleichzeitigen Neustarts begrenzt, und es kann vermieden werden, dass der Server insgesamt keine Anforderungen empfangen kann.

touch-reload, lazy-apps

Sie können den Dateipfad in touch-reload angeben und uWSGI jedes Mal neu laden, wenn die Einstellung berührt wird. In diesem Fall kann jedoch nicht der gesamte Server Anforderungen empfangen, sodass Sie Lazy-Apps so einstellen können, dass Sie sie nacheinander neu laden können.

Wenn in unserer Umgebung Lazy-Apps angegeben sind, können diese nicht sofort aktualisiert werden. Daher dürfen wir nicht einige Sekunden warten und diese festlegen.

Zusammenfassung

Dieses Mal haben wir die Parameter von uWSGI gesehen, die tatsächlich optimiert wurden. Darüber hinaus wurden die folgenden Parameter festgelegt, aber ich möchte weitere Untersuchungen durchführen und die Leistung verbessern.

Recommended Posts

Webserver als Ersatz für Apache: uWSGI-Leistungsoptimierung
Aufbau eines Linux-Webservers (Ubuntu & Apache)
Eine Einführung in die Programmleistungsoptimierung
Quellkompilierung Apache2.4 (httpd 2.4.43) + PHP7.4 unter Linux zum Erstellen eines Webservers --3 MySQL 8.0 Einführung
CTF-Anfänger haben versucht, einen Problemserver (Web) zu erstellen [Problem]