Gunicorn Arbeiter und Fäden

72

In Bezug auf Gunicorn bin ich mir bewusst, dass es verschiedene Arbeiterklassen gibt, aber für dieses Gespräch betrachte ich nur die Synchronisierungs- und Asynchronisierungstypen.

Meinem Verständnis nach ...

sync
workers = (2 * cpu) + 1
worker_class = sync

async (gevent)
workers = 1
worker_class = gevent
worker_connections = a value (lets say 2000)

Daher kann ich (basierend auf einem 4-Kern-System) mit Sync-Workern maximal 9 Verbindungen parallel verarbeiten. Mit Async kann ich bis zu 2000 haben, mit den Einschränkungen, die mit Async einhergehen.

Fragen

  • Wo passen die Fäden hin? Kann ich den Synchron- und Async-Worker-Typen Threads hinzufügen?
  • Was ist die beste Option für Gunicorn-Arbeiter? Sollte ich Gunicorn vor einer Django-API platzieren wollen, wobei Hunderte von Anfragen parallel verarbeitet werden müssen?
  • Sind Gevent- und Sync-Worker-Klassen threadsicher?
felix001
quelle

Antworten:

136

Lassen Sie mich eine Antwort versuchen. Nehmen wir an, dass mein Einsatz zu Beginn nur einen einzigen Gunicorn-Arbeiter hat. Dadurch kann ich jeweils nur eine Anfrage bearbeiten. Die Arbeit meines Mitarbeiters besteht nur darin, google.com anzurufen und die Suchergebnisse für eine Abfrage abzurufen. Jetzt möchte ich meinen Durchsatz erhöhen. Ich habe die folgenden Optionen

Behalten Sie nur einen Worker und erhöhen Sie die Anzahl der Threads in diesem Worker

Das ist am einfachsten. Da Threads leichter sind (weniger Speicherverbrauch) als Prozesse, behalte ich nur einen Worker und füge dem mehrere Threads hinzu. Gunicorn stellt sicher, dass der Meister dann mehr als eine Anfrage an den Arbeiter senden kann. Da der Worker Multithreading ist, kann er 4 Anforderungen verarbeiten. Fantastisch. Warum sollte ich jemals mehr Arbeiter brauchen?

Um dies zu beantworten, nehmen wir an, dass ich einige Arbeiten an den von Google zurückgegebenen Suchergebnissen durchführen muss. Zum Beispiel möchte ich vielleicht auch eine Primzahl für jede Ergebnisabfrage berechnen. Jetzt mache ich meine Workload-Berechnung gebunden und stoße auf das Problem mit der globalen Interpretersperre von Python. Obwohl ich 4 Threads habe, kann jeweils nur ein Thread die Ergebnisse verarbeiten. Dies bedeutet, dass ich mehr als einen Mitarbeiter benötige, um eine echte parallele Leistung zu erzielen.

Erhöhen Sie die Anzahl der Arbeiter, aber alle Arbeiter haben einen einzigen Thread

Warum ich das brauche, ist, wenn ich echte Parallelverarbeitung brauche. Jeder Mitarbeiter kann parallel zu google.com anrufen, Ergebnisse abrufen und die Verarbeitung durchführen. Alles parallel. Fantastisch. Der Nachteil ist jedoch, dass die Prozesse schwerer sind und mein System möglicherweise nicht mit den Anforderungen steigender Mitarbeiter Schritt hält, um Parallelität zu erreichen. Die beste Lösung besteht also darin, die Anzahl der Mitarbeiter zu erhöhen und jedem Mitarbeiter mehr Threads hinzuzufügen.

Erhöhen Sie die Anzahl der Mitarbeiter, und jeder Mitarbeiter verfügt über mehrere Threads

Ich denke, das bedarf keiner weiteren Erklärung.

Ändern Sie den Arbeitertyp in Async

Warum sollte ich das jemals tun wollen? Denken Sie zur Beantwortung daran, dass selbst Threads Speicher belegen. Es gibt Coroutinen (ein radikales Konstrukt, das Sie nachschlagen können), die von der Gevent-Bibliothek implementiert wurden und die es Ihnen ermöglichen, Threads abzurufen, ohne Threads erstellen zu müssen. Wenn Sie also Ihr Gunicorn so herstellen, dass es ein Arbeiter-Gevent verwendet, haben Sie den Vorteil, dass Sie KEINE Threads in Ihren Arbeitern erstellen müssen. Angenommen, Sie erhalten Threads, ohne diese explizit erstellen zu müssen.

Um Ihre Frage zu beantworten: Wenn Sie worker_type von etwas anderem als Sync verwenden, müssen Sie die Anzahl der Threads in Ihrer Gunicorn-Konfiguration nicht erhöhen. Sie können es auf jeden Fall tun, aber es macht den Zweck irgendwie zunichte.

Hoffe das hat geholfen.

Ich werde auch versuchen, die spezifischen Fragen zu beantworten.

  • Nein, die Thread-Option ist für die Async-Worker-Klasse nicht vorhanden. Dies muss tatsächlich durch die Dokumentation klarer gemacht werden. Ich frage mich, warum das nicht passiert ist.

  • Dies ist eine Frage, die mehr Wissen über Ihre spezifische Anwendung erfordert. Wenn die Verarbeitung dieser 100 parallelen Anforderungen nur E / A-Vorgänge umfasst, z. B. Abrufen aus der Datenbank, Speichern und Sammeln von Daten aus einer anderen Anwendung, können Sie den Threaded-Worker verwenden. Wenn dies jedoch nicht der Fall ist und Sie auf einer Kern-CPU ausführen möchten, weil die Aufgaben extrem rechengebunden sind, z. B. beim Berechnen von Primzahlen, müssen Sie den Sync-Worker verwenden. Die Argumentation für Async ist etwas anders. Um Async verwenden zu können, müssen Sie sicherstellen, dass Ihre Verarbeitung nicht an Berechnungen gebunden ist. Dies bedeutet, dass Sie nicht mehrere Kerne verwenden können. Der Vorteil, den Sie erhalten, ist, dass der Speicher, den mehrere Threads benötigen würden, nicht vorhanden wäre. Sie haben jedoch andere Probleme, z. B. Bibliotheken, die nicht mit Affen gepatcht sind.

  • Synchronisierte Worker ohne Thread sind die beste Option, wenn Sie absolute Thread-Sicherheit in Ihren Bibliotheken wünschen.

abhayAndPoorvisDad
quelle
Aber aufgrund von GIL, warum nicht immer asynchron ausführen, auch wenn die Berechnung gebunden ist. Die Gewindesicherheit ist bereits gewährleistet.
Garg10Mai
5
Wenn ich mich in die Lage eines solchen versetze, der sich dazu entschließen könnte, hätte ich Angst davor, welche Module möglicherweise nicht richtig gepatcht werden, um vorhersehbar zu funktionieren, wenn die Async-Arbeiterklasse verwendet wird. Async mit all seinen Vorteilen ist mit eigenen Risiken verbunden. Sie müssen unbedingt sicherstellen, dass Ihr gesamter Code mit Affen gepatcht ist und kein nativer Code ausgeführt wird. Dieses Risiko würde mich also daran hindern, immer asynchron zu werden.
abhayAndPoorvisDad
1
gute Antwort. Es ist mir immer noch unklar, warum / wie Bibliotheken mit Affen gepatcht werden sollten und ob es eine Möglichkeit gibt, zu überprüfen, ob dies der Fall ist.
Paolo
1
Stellen Arbeiter mit Gewinde im Vergleich zu Arbeitern ohne Gewinde ein erhebliches Risiko für Sicherheitsfehler dar? Müssen Bibliotheken für das Synchronisieren von Thread-Workern mit Affen gepatcht werden?
Antony Mativos