committed by
GitHub
1 changed files with 180 additions and 0 deletions
@ -0,0 +1,180 @@ |
|||
# 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](concepts.md){.internal-link target=_blank} gesehen haben, gibt es mehrere Strategien, die Sie anwenden können. |
|||
|
|||
Hier zeige ich Ihnen, wie Sie <a href="https://gunicorn.org/" class="external-link" target="_blank">**Gunicorn**</a> 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](docker.md){.internal-link target=_blank}. |
|||
|
|||
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 **<a href="https://asgi.readthedocs.io/en/latest/" class="external-link" target="_blank">ASGI-Standard</a>** 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 |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install "uvicorn[standard]" gunicorn |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
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: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ 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. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
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: |
|||
|
|||
```Python |
|||
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: |
|||
|
|||
```Python |
|||
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: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ 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. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
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](docker.md){.internal-link target=_blank} 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. ✨ |
Loading…
Reference in new issue