Wie viele Prozesse sollte ich in einem WSGIDaemonProcess angeben, während Django über mod_wsgi ausgeführt wird?


23

Angenommen, ich habe zwei Sites (Superuser und Serverfault), die von einem eigenen virtuellen Apache-Host auf einer Box ausgeführt werden. Die beiden Sites werden von Django betrieben und laufen unter Apache mit mod-wsgi. Eine typische Konfigurationsdatei für eine der Sites sieht folgendermaßen aus:

WSGIDaemonProcess serverfault.com user=www-data group=www-data processes=5

Der Host ist ein Linux-Rechner mit 4 GB RAM, auf dem Ubuntu ausgeführt wird. Kann jemand die Anzahl der Prozesse vorschlagen, die ich oben für meine 2 Sites angeben sollte? Angenommen, sie haben denselben Datenverkehr wie die tatsächlichen Superuser- und Serverfault-Sites.

Antworten:


22

Nun, wie viel Verkehr haben die tatsächlichen Superuser- und Serverfault-Sites? Hypothesen nützen nicht viel, wenn sie nicht genug Informationen haben, um die Antwort zu erleichtern ...

Die Prozessanzahl im ungünstigsten Fall sollte die maximale Anzahl der Anforderungen pro Sekunde sein, die die Site verarbeiten kann, geteilt durch die Anzahl der Anforderungen pro Sekunde, die ein Prozess verarbeiten kann, wenn alle diese Anforderungen an Ihre langsamste Aktion gesendet werden (z. B. den Kehrwert der Bearbeitungszeit dieser Aktion). Fügen Sie den gewünschten Fudge-Faktor hinzu, basierend auf dem Konfidenzintervall Ihrer Anforderungs- / Sekunden- und Zeitmessungen.

Die durchschnittliche Fallzahl ist dieselbe, aber Sie dividieren die Anforderung / Sek. Durch das gewichtete Mittel Ihrer Anforderungen pro Sekunde für jede Aktion (die Gewichtung gibt den Prozentsatz der Anforderungen an, von denen Sie erwarten, dass sie diese bestimmte Aktion treffen). Auch hier sind Fudge-Faktoren nützlich.

Die tatsächliche Obergrenze für die Anzahl der Prozesse, die Sie auf dem Computer ausführen können, hängt von der Speichergröße ab, die jeder Prozess benötigt. Spoolen Sie einen Prozess und führen Sie dann eine Reihe von speicherhungrigen Aktionen aus (die normalerweise viele Daten abrufen und verarbeiten), wobei Sie einen realistischen Datensatz verwenden (wenn Sie nur einen Spielzeugdatensatz zum Testen verwenden, z. B. 50 oder 100) Wenn dann eine Ihrer Aktionen jede Zeile in der Tabelle abruft und manipuliert, ist dies kein gutes Maß dafür, wann diese Tabelle auf 10.000 Zeilen anwächst, um zu sehen, wie hoch die Speichernutzung ist. Sie können die Speichernutzung pro Prozess künstlich einschränken, indem Sie ein Skript verwenden, das Worker abruft, die einen bestimmten Schwellenwert für die Speichernutzung erreichen. Dies kann zu unangenehmen Problemen führen, wenn Sie diesen Schwellenwert zu niedrig festlegen.

Sobald Sie Ihre Speicherauslastung ermittelt haben, ziehen Sie eine gewisse Menge an Speicher für den System-Overhead ab (ich selbst mag 512 MB), ziehen einen Stapel mehr ab, wenn andere Prozesse auf demselben Computer ausgeführt werden (wie eine Datenbank), und dann einige mehr, um sicherzustellen, dass Ihnen nicht der Cache-Speicherplatz ausgeht (hängt von der Größe Ihres Arbeitsspeichers ab, aber auch hier würde ich nicht weniger als 512 MB verwenden). Dies ist die Speichermenge, die Sie durch die prozessbezogene Speichernutzung dividieren, um die Obergrenze zu erreichen.

Wenn die Anzahl der Prozesse, die Sie zur Wartung Ihrer Spitzenlast benötigen, größer ist als die Anzahl der Prozesse, die Sie in die Box einpassen können, benötigen Sie mehr Computer (oder im einfachsten Fall, um die Datenbank auf einen anderen Computer zu verschieben).

Sie haben mehrere Jahre Erfahrung in der Skalierung von Websites, die in einem kleinen und einfachen SF-Beitrag zusammengefasst sind.


Ein weiterer wichtiger Faktor für die Anzahl der Prozesse / Threads ist, wie lange es dauern kann, einzelne Anforderungen zu bearbeiten, und die Gesamtverteilung über alle möglichen Zeitspannen. Mit anderen Worten, wie viele Anfragen gleichzeitig bearbeitet werden müssen, die länger als die durchschnittliche Antwortzeit dauern. Es ist also nicht so einfach wie nur theoretische Anforderungen / Sek., Da die Auswirkungen dieser länger laufenden Anforderungen erheblich sein und die allgemeinen Konfigurationsparameter übermäßig bestimmen können. FWIW mod_wsgi 3.0 wird eine integrierte Statistiksammlung enthalten, um zu versuchen, Daten darüber zu erfassen, um die Konfiguration zu unterstützen.
Graham Dumpleton

@ Abraham: Lies noch einmal meine Antwort, ich habe das etwas detaillierter behandelt. Requests / sec ist nur der Kehrwert der Antwortzeit, und es ist einfacher, durch eine ganze Zahl req / sec zu dividieren, als mit einer Dezimalzahl zu multiplizieren.
womble

Sie können sich jedoch nicht nur auf die Worst-Case-Reaktion konzentrieren, sondern auch nicht nur auf den Durchschnitt. Es muss auf eine Weise gewichtet werden, die auf dem Prozentsatz der Anfragen basiert, die in Zeiträume fallen, dh der Verteilung über alle möglichen Zeiträume. Wenn Sie wirklich Ihre Worst-Case-Reaktionszeit in Anspruch genommen hätten, hätten Sie unrealistische Anforderungen. Das Problem ist es wirklich schwer zu wissen, welche Formel zu verwenden ist. Aus diesem Grund wird in mod_wsgi 3.0 eine integrierte Statistik erfasst, die die Thread-Auslastung und den Prozentsatz nach Anzahl und Zeit angibt, zu dem eine beliebige Anzahl von Threads gleichzeitig verwendet wird.
Graham Dumpleton

3
Das Problem ist vielleicht, dass Sie nur auf Prozesse schauen, bei denen ich mir Sorgen mache, wie die Threads, die jeder Prozess verwendet, dies berücksichtigen und das ist nicht so einfach. Mit anderen Worten, diese WSGIDaemonProcess-Direktive gibt 5 Prozesse an, wobei jeder Prozess standardmäßig 15 Threads verwendet. Soweit ich in Ihre Beschreibung gelesen habe, wird von Single-Thread-Prozessen ausgegangen. Wenn nicht, weisen Sie mich darauf hin, wie Ihr Modell Threads und Konflikt- / Skalierungsprobleme rund um die GIL behebt. Qualifizieren Sie also, dass Ihre Beschreibung nur für Prozesse mit einem Thread gültig ist, und ich werde nicht streiten.
Graham Dumpleton

2
Ist der Ansatz "multithreaded-Apache + multiprocess-wsgi" nicht die beste Wahl, bis Sie zu 99% sicher sind, dass Ihr Python-Code und alle Abhängigkeiten thread-sicher sind?
Tomasz Zieliński

9

Die Antwort von womble ist großartig, wenn auch etwas schwer zu verstehen und für Unerfahrene zu beantragen. Ich möchte einige empirische Zahlen und den Vergleich von "einfachen Inhalten" und "E-Commerce" -Anwendungen nennen.

Es gibt nicht viel Material, um verschiedene Anwendungsfälle in Bezug auf die entsprechende Konfiguration von mod_wsgi festzulegen, daher hoffe ich, dass es in Ordnung ist, hier eine kleine Prosa zu verwenden.

A) CMS Sites & Microsites

Wir betreiben mehrere Kundenwebsites, von denen die meisten Content-Websites oder Micro-Websites sind, auf denen Django CMS, einige benutzerdefinierte Formulare und manchmal Sellerie für geplante Hintergrundaufgaben gehostet werden. Diese Sites sind nicht ressourcenhungrig. Einige von ihnen laufen problemlos parallel auf einem einzigen 4-Core Intel Xeon mit 32 GB RAM. Hier ist die Konfiguration, die wir für jede dieser Sites verwenden:

WSGIDaemonProcess example.com user=www-data processes=2 maximum-requests=100

Ich spreche von ungefähr 40 Sites auf einem einzelnen Server, von denen die meisten mit ihrer Staging-Site im Standby-Modus ausgeführt werden. Mit 2 Prozessen (standardmäßig mit jeweils 15 Threads) sind die Sites gut ausgelastet, auch wenn ihre Fähigkeit zur Zuweisung von Serverressourcen eingeschränkt ist. Warum dieses Setup ausreicht, lässt sich mit der einfachen Art der (CMS-) Anwendung begründen: Es wird nie erwartet, dass eine Anforderung länger als ein paar Millisekunden dauert. Apache bleibt immer entspannt, ebenso wie die CPU-Last.

B) E-Commerce-Sites

Komplexere Sites, die wir anbieten, zeichnen sich durch immer noch rechengünstige lokale Operationen aus, aber externe Abhängigkeiten (z. B. Webdienste, die Buchungsdaten bereitstellen), die in Bezug auf die Transaktionszeit teuer sind. Vorgänge mit externen Anforderungen belegen Threads viel länger, sodass Sie mehr Threads benötigen, um die gleiche Anzahl von Benutzern zu bedienen (im Vergleich zu einer einfachen CMS-Site von oben). Noch schlimmer ist, dass Threads gelegentlich blockiert werden, wenn ein externer Dienst eine Anfrage nicht sofort beantworten kann, manchmal für ein paar Sekunden. Dies kann zu dem unangenehmen Nebeneffekt führen, dass Threads, die Anforderungen an dieselbe Servicewarteschlange senden, so lange in Betrieb bleiben, bis alle verfügbaren mod_wsgi-Threads aufgebraucht sind und das Warten blockiert wird.

In diesen Szenarien haben wir versucht, 6Prozesse zu verwenden , ohne große Unterschiede zu bemerken, und 12dabei eine unvergleichliche Steigerung der Leistung und der Betriebsstabilität festgestellt:

WSGIDaemonProcess example.com user=www-data processes=12 maximum-requests=100

Einige einfache Auslastungstests mit 150 und 250 parallelen Benutzern können von der Site problemlos durchgeführt werden, wobei die Site gut reagiert (während 2die Site bei Prozessen nicht mehr für die gleichzeitige Verpflegung von 50 Benutzern geeignet ist). Der Intel Xeon mit 2 CPUs und 6 Kernen und 32 GB RAM ist unter dieser Last mit deutlich weniger als 25% der CPU ausgelastet. Auch die RAM-Auslastung bleibt mit weniger als 25% nahezu konstant. Beachten Sie, dass wir hier einen dedizierten Computer nur für einen einzelnen Standort verwenden, damit wir keine Ressourcen stehlen, die andere Standorte möglicherweise benötigen.

Fazit

Die Verwendung einer höheren Anzahl von Prozessen ist ein Kompromiss zwischen dem Ermöglichen, dass Apache die verfügbaren Systemressourcen nutzt oder nicht. Wenn Sie ein stabiles Serversystem (nicht Website!) Unter "Angriffsbedingungen" betreiben möchten, halten Sie die Anzahl niedrig. Wenn Sie möchten, dass Apache Sie bei Bedarf bei der Verwendung von Systemressourcen (CPU, RAM) unterstützt, wählen Sie eine höhere Zahl. Wie hoch Sie gehen können, hängt in etwa von der oben angegebenen akzeptierten Antwort ab und wird letztendlich durch die verfügbare CPU-Leistung und den verfügbaren Arbeitsspeicher eingeschränkt.

(PS: Ich behalte den Abschnitt "ConfigurationDirectives" des Modwsgi-Projekt-Wikis unter meinem Kopfkissen, damit ich Apache-ähnliche Hintergrundinformationen lesen kann. Vergewissern Sie sich auch, dass Sie die offenen Verbindungen Ihres Apache-Servers verstehen und überwachen .)


Toller Beitrag, aber warum stellst du nicht die Threadanzahl ein? Da Pythons GIL viele der Vorteile von Threads negiert, würde ich annehmen, dass Sie mehr Prozesse als Threads haben möchten. Gibt es jedoch einen Vorteil bei der Angabe der Thread-Anzahl?
Cerin

Die Standardanzahl von threads15 ist laut Dokumentation . Ich glaube nicht, dass es von Vorteil ist, dies explizit anzugeben. Tatsächlich erinnere ich mich, dass ich es aus einem Grund weggelassen habe: Es gab einen Post auf SO oder einen Teil einer Dokumentation, in der empfohlen wurde, den Wert wegzulassen, um Nebenwirkungen zu vermeiden (ich weiß, das klingt komisch). Leider finde ich diese Quelle jetzt nicht. Für den Rest Ihrer Frage (GIL) sind Sie wahrscheinlich kompetenter als ich, sorry.
Peterino

Vielen Dank für diese empirische Konfiguration. You should never use maximum-requests in a production system unless you understand the implications and have a specific temporary need.
Bedenken
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.