Zum Inhalt

Serverworker – Gunicorn mit Uvicorn

Schauen wir uns die Deployment-Konzepte von früher noch einmal an:

  • Sicherheit – HTTPS
  • Beim Hochfahren ausführen
  • Neustarts
  • Replikation (die Anzahl der laufenden Prozesse)
  • Arbeitsspeicher
  • Schritte vor dem Start

Bis zu diesem Punkt, in allen Tutorials in der Dokumentation, haben Sie wahrscheinlich ein Serverprogramm wie Uvicorn ausgeführt, in einem einzelnen Prozess.

Wenn Sie Anwendungen bereitstellen, möchten Sie wahrscheinlich eine gewisse Replikation von Prozessen, um mehrere CPU-Kerne zu nutzen und mehr Requests bearbeiten zu können.

Wie Sie im vorherigen Kapitel über Deployment-Konzepte gesehen haben, gibt es mehrere Strategien, die Sie anwenden können.

Hier zeige ich Ihnen, wie Sie Gunicorn mit Uvicorn Workerprozessen verwenden.

Info

Wenn Sie Container verwenden, beispielsweise mit Docker oder Kubernetes, erzähle ich Ihnen mehr darüber im nächsten Kapitel: FastAPI in Containern – Docker.

Insbesondere wenn die Anwendung auf Kubernetes läuft, werden Sie Gunicorn wahrscheinlich nicht verwenden wollen und stattdessen einen einzelnen Uvicorn-Prozess pro Container ausführen wollen, aber ich werde Ihnen später in diesem Kapitel mehr darüber erzählen.

Gunicorn mit Uvicorn-Workern

Gunicorn ist hauptsächlich ein Anwendungsserver, der den WSGI-Standard verwendet. Das bedeutet, dass Gunicorn Anwendungen wie Flask und Django ausliefern kann. Gunicorn selbst ist nicht mit FastAPI kompatibel, da FastAPI den neuesten ASGI-Standard verwendet.

Aber Gunicorn kann als Prozessmanager arbeiten und Benutzer können ihm mitteilen, welche bestimmte Workerprozessklasse verwendet werden soll. Dann würde Gunicorn einen oder mehrere Workerprozesse starten, diese Klasse verwendend.

Und Uvicorn hat eine Gunicorn-kompatible Workerklasse.

Mit dieser Kombination würde Gunicorn als Prozessmanager fungieren und den Port und die IP abhören. Und er würde die Kommunikation an die Workerprozesse weiterleiten, welche die Uvicorn-Klasse ausführen.

Und dann wäre die Gunicorn-kompatible Uvicorn-Worker-Klasse dafür verantwortlich, die von Gunicorn gesendeten Daten in den ASGI-Standard zu konvertieren, damit FastAPI diese verwenden kann.

Gunicorn und Uvicorn installieren

$ pip install "uvicorn[standard]" gunicorn

---> 100%

Dadurch wird sowohl Uvicorn mit zusätzlichen standard-Packages (um eine hohe Leistung zu erzielen) als auch Gunicorn installiert.

Gunicorn mit Uvicorn-Workern ausführen

Dann können Sie Gunicorn ausführen mit:

$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80

[19499] [INFO] Starting gunicorn 20.1.0
[19499] [INFO] Listening at: http://0.0.0.0:80 (19499)
[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker
[19511] [INFO] Booting worker with pid: 19511
[19513] [INFO] Booting worker with pid: 19513
[19514] [INFO] Booting worker with pid: 19514
[19515] [INFO] Booting worker with pid: 19515
[19511] [INFO] Started server process [19511]
[19511] [INFO] Waiting for application startup.
[19511] [INFO] Application startup complete.
[19513] [INFO] Started server process [19513]
[19513] [INFO] Waiting for application startup.
[19513] [INFO] Application startup complete.
[19514] [INFO] Started server process [19514]
[19514] [INFO] Waiting for application startup.
[19514] [INFO] Application startup complete.
[19515] [INFO] Started server process [19515]
[19515] [INFO] Waiting for application startup.
[19515] [INFO] Application startup complete.

Sehen wir uns an, was jede dieser Optionen bedeutet:

  • main:app: Das ist die gleiche Syntax, die auch von Uvicorn verwendet wird. main bedeutet das Python-Modul mit dem Namen main, also eine Datei main.py. Und app ist der Name der Variable, welche die FastAPI-Anwendung ist.

    • Stellen Sie sich einfach vor, dass main:app einer Python-import-Anweisung wie der folgenden entspricht:

      from main import app
      
    • Der Doppelpunkt in main:app entspricht also dem Python-import-Teil in from main import app.

  • --workers: Die Anzahl der zu verwendenden Workerprozesse, jeder führt einen Uvicorn-Worker aus, in diesem Fall 4 Worker.

  • --worker-class: Die Gunicorn-kompatible Workerklasse zur Verwendung in den Workerprozessen.

    • Hier übergeben wir die Klasse, die Gunicorn etwa so importiert und verwendet:

      import uvicorn.workers.UvicornWorker
      
  • --bind: Das teilt Gunicorn die IP und den Port mit, welche abgehört werden sollen, wobei ein Doppelpunkt (:) verwendet wird, um die IP und den Port zu trennen.

    • Wenn Sie Uvicorn direkt ausführen würden, würden Sie anstelle von --bind 0.0.0.0:80 (die Gunicorn-Option) stattdessen --host 0.0.0.0 und --port 80 verwenden.

In der Ausgabe können Sie sehen, dass die PID (Prozess-ID) jedes Prozesses angezeigt wird (es ist nur eine Zahl).

Sie können sehen, dass:

  • Der Gunicorn Prozessmanager beginnt, mit der PID 19499 (in Ihrem Fall ist es eine andere Nummer).
  • Dann beginnt er zu lauschen: Listening at: http://0.0.0.0:80.
  • Dann erkennt er, dass er die Workerklasse uvicorn.workers.UvicornWorker verwenden muss.
  • Und dann werden 4 Worker gestartet, jeder mit seiner eigenen PID: 19511, 19513, 19514 und 19515.

Gunicorn würde sich bei Bedarf auch um die Verwaltung beendeter Prozesse und den Neustart von Prozessen kümmern, um die Anzahl der Worker aufrechtzuerhalten. Das hilft also teilweise beim Neustarts-Konzept aus der obigen Liste.

Dennoch möchten Sie wahrscheinlich auch etwas außerhalb haben, um sicherzustellen, dass Gunicorn bei Bedarf neu gestartet wird, und er auch beim Hochfahren ausgeführt wird, usw.

Uvicorn mit Workern

Uvicorn bietet ebenfalls die Möglichkeit, mehrere Workerprozesse zu starten und auszuführen.

Dennoch sind die Fähigkeiten von Uvicorn zur Abwicklung von Workerprozessen derzeit eingeschränkter als die von Gunicorn. Wenn Sie also einen Prozessmanager auf dieser Ebene (auf der Python-Ebene) haben möchten, ist es vermutlich besser, es mit Gunicorn als Prozessmanager zu versuchen.

Wie auch immer, Sie würden es so ausführen:

$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
<font color="#A6E22E">INFO</font>:     Uvicorn running on <b>http://0.0.0.0:8080</b> (Press CTRL+C to quit)
<font color="#A6E22E">INFO</font>:     Started parent process [<font color="#A1EFE4"><b>27365</b></font>]
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27368</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27369</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27370</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.
<font color="#A6E22E">INFO</font>:     Started server process [<font color="#A1EFE4">27367</font>]
<font color="#A6E22E">INFO</font>:     Waiting for application startup.
<font color="#A6E22E">INFO</font>:     Application startup complete.

Die einzige neue Option hier ist --workers, die Uvicorn anweist, 4 Workerprozesse zu starten.

Sie können auch sehen, dass die PID jedes Prozesses angezeigt wird, 27365 für den übergeordneten Prozess (dies ist der Prozessmanager) und eine für jeden Workerprozess: 27368, 27369, 27370 und 27367.

Deployment-Konzepte

Hier haben Sie gesehen, wie Sie mit Gunicorn (oder Uvicorn) Uvicorn-Workerprozesse verwalten, um die Ausführung der Anwendung zu parallelisieren, mehrere Kerne der CPU zu nutzen und in der Lage zu sein, mehr Requests zu bedienen.

In der Liste der Deployment-Konzepte von oben würde die Verwendung von Workern hauptsächlich beim Replikation-Teil und ein wenig bei Neustarts helfen, aber Sie müssen sich trotzdem um die anderen kümmern:

  • Sicherheit – HTTPS
  • Beim Hochfahren ausführen
  • Neustarts
  • Replikation (die Anzahl der laufenden Prozesse)
  • Arbeitsspeicher
  • Schritte vor dem Start

Container und Docker

Im nächsten Kapitel über FastAPI in Containern – Docker werde ich einige Strategien erläutern, die Sie für den Umgang mit den anderen Deployment-Konzepten verwenden können.

Ich zeige Ihnen auch das offizielle Docker-Image, welches Gunicorn mit Uvicorn-Workern und einige Standardkonfigurationen enthält, die für einfache Fälle nützlich sein können.

Dort zeige ich Ihnen auch, wie Sie Ihr eigenes Image von Grund auf erstellen, um einen einzelnen Uvicorn-Prozess (ohne Gunicorn) auszuführen. Es ist ein einfacher Vorgang und wahrscheinlich das, was Sie tun möchten, wenn Sie ein verteiltes Containerverwaltungssystem wie Kubernetes verwenden.

Zusammenfassung

Sie können Gunicorn (oder auch Uvicorn) als Prozessmanager mit Uvicorn-Workern verwenden, um Multikern-CPUs zu nutzen und mehrere Prozesse parallel auszuführen.

Sie können diese Tools und Ideen nutzen, wenn Sie Ihr eigenes Deployment-System einrichten und sich dabei selbst um die anderen Deployment-Konzepte kümmern.

Schauen Sie sich das nächste Kapitel an, um mehr über FastAPI mit Containern (z. B. Docker und Kubernetes) zu erfahren. Sie werden sehen, dass diese Tools auch einfache Möglichkeiten bieten, die anderen Deployment-Konzepte zu lösen. ✨