@ -1,4 +1,4 @@
# Server Workers - Gunicorn with Uvicorn
# 服务器工作进程(Workers) - 使用 Uvicorn 的多工作进程模式
让我们回顾一下之前的部署概念:
让我们回顾一下之前的部署概念:
@ -9,125 +9,79 @@
* 内存
* 内存
* 启动前的先前步骤
* 启动前的先前步骤
到目前为止,通过文档中的所有教程,您可能已经在**单个进程**上运行了像 Uvicorn 这样的**服务器程序 **。
到目前为止,在文档中的所有教程中,您可能一直是在运行一个**服务器程序**,例如使用 `fastapi` 命令来启动 Uvicorn,而它默认运行的是**单进程模式 **。
部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核**并能够处理更多请求。
部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核** CPU 并能够处理更多请求。
正如您在上一章有关[部署概念](concepts.md){.internal-link target=_blank}中看到的,您可以使用多种策略。
正如您在上一章有关[部署概念](concepts.md){.internal-link target=_blank}中看到的,您可以使用多种策略。
在这里我将向您展示如何将 < a href = "https://gunicorn.org/" class = "external-link" target = "_blank" > **Gunicorn**</ a > 与 **Uvicorn worker 进程** 一起使用 。
在本章节中,我将向您展示如何使用 `fastapi` 命令或直接使用 `uvicorn` 命令以**多工作进程模式**运行 **Uvicorn** 。
/// info
/// info
如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。
如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。
特别是,当在 **Kubernetes** 上运行时,您可能**不想**使用 Gunicorn,而是运行 **每个容器一个 Uvicorn 进程** ,但我将在本章后面告诉您 这一点。
比较特别的是,在 **Kubernetes** 环境中运行时,您通常**不需要**使用多个工作进程,而是**每个容器运行一个 Uvicorn 进程**。不过,我会在本章节的后续部分详细介绍 这一点。
///
///
## Gunicorn with Uvicorn Workers
## 多个工作进程
**Gunicorn**主要是一个使用**WSGI标准**的应用服务器。 这意味着 Gunicorn 可以为 Flask 和 Django 等应用程序提供服务。 Gunicorn 本身与 **FastAPI** 不兼容,因为 FastAPI 使用最新的 ** < a href = "https://asgi.readthedocs.io/en/latest/" class = "external-link" target = " _blank" > ASGI 标准</ a > **。
您可以使用 `--workers` 命令行选项来启动多个工作进程:
但 Gunicorn 支持充当 **进程管理器** 并允许用户告诉它要使用哪个特定的 **worker类** 。 然后 Gunicorn 将使用该类启动一个或多个 **worker进程** 。
//// tab | `fastapi`
**Uvicorn** 有一个 Gunicorn 兼容的worker类。
如果您使用 `fastapi` 命令:
使用这种组合,Gunicorn 将充当 **进程管理器** ,监听 **端口** 和 **IP** 。 它会将通信**传输**到运行**Uvicorn类**的worker进程。
然后与Gunicorn兼容的**Uvicorn worker**类将负责将Gunicorn发送的数据转换为ASGI标准以供FastAPI使用。
## 安装 Gunicorn 和 Uvicorn
< div class = "termy" >
< div class = "termy" >
```console
```console
$ pip install "uvicorn[standard]" gunicorn
$ < font color = "#4E9A06" > fastapi< / font > run --workers 4 < u style = "text-decoration-style:solid" > main.py< / u >
---> 100%
```
< / div >
这将安装带有`standard`扩展包(以获得高性能)的 Uvicorn 和 Gunicorn。
< span style = "background-color:#009485" > < font color = "#D3D7CF" > FastAPI < / font > < / span > Starting production server 🚀
## Run Gunicorn with Uvicorn Workers
Searching for package file structure from directories with
< font color = "#3465A4" > __init__.py< / font > files
Importing from < font color = "#75507B" > /home/user/code/< / font > < font color = "#AD7FA8" > awesomeapp< / font >
接下来你可以通过以下命令运行Gunicorn:
< span style = "background-color:#007166" > < font color = "#D3D7CF" > module < / font > < / span > 🐍 main.py
< 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 >
< span style = "background-color:#007166" > < font color = "#D3D7CF" > code < / font > < / span > Importing the FastAPI app object from the module with the
following code:
让我们看看每个选项的含义:
< u style = "text-decoration-style:solid" > from < / u > < u style = "text-decoration-style:solid" > < b > main< / b > < / u > < u style = "text-decoration-style:solid" > import < / u > < u style = "text-decoration-style:solid" > < b > app< / b > < / u >
* `main:app` :这与 Uvicorn 使用的语法相同,`main` 表示名为"`main`"的 Python 模块,因此是文件 `main.py` 。 `app` 是 **FastAPI** 应用程序的变量名称。
< span style = "background-color:#007166" > < font color = "#D3D7CF" > app < / font > < / span > Using import string: < font color = "#3465A4" > main:app< / font >
* 你可以想象 `main:app` 相当于一个 Python `import` 语句,例如:
```Python
< span style = "background-color:#007166" > < font color = "#D3D7CF" > server < / font > < / span > Server started at < font color = "#729FCF" > < u style = "text-decoration-style:solid" > http://0.0.0.0:8000< / u > < / font >
from main import app
< span style = "background-color:#007166" > < font color = "#D3D7CF" > server < / font > < / span > Documentation at < font color = "#729FCF" > < u style = "text-decoration-style:solid" > http://0.0.0.0:8000/docs< / u > < / font >
```
* 因此,`main:app` 中的冒号相当于 `from main import app` 中的 Python `import` 部分。
Logs:
* `--workers` :要使用的worker进程数量,每个进程将运行一个 Uvicorn worker进程,在本例中为 4 个worker进程。
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Uvicorn running on < font color = "#729FCF" > < u style = "text-decoration-style:solid" > http://0.0.0.0:8000< / u > < / font > < b > (< / b > Press CTRL+C to
quit< b > )< / b >
* `--worker-class` :在worker进程中使用的与 Gunicorn 兼容的工作类。
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Started parent process < b > [< / b > < font color = "#34E2E2" > < b > 27365< / b > < / font > < b > ]< / b >
* 这里我们传递了 Gunicorn 可以导入和使用的类:
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Started server process < b > [< / b > < font color = "#34E2E2" > < b > 27368< / b > < / font > < b > ]< / b >
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Started server process < b > [< / b > < font color = "#34E2E2" > < b > 27369< / b > < / font > < b > ]< / b >
```Python
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Started server process < b > [< / b > < font color = "#34E2E2" > < b > 27370< / b > < / font > < b > ]< / b >
import uvicorn.workers.UvicornWorker
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Started server process < b > [< / b > < font color = "#34E2E2" > < b > 27367< / b > < / font > < b > ]< / b >
```
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Waiting for application startup.
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Waiting for application startup.
* `--bind` :这告诉 Gunicorn 要监听的 IP 和端口,使用冒号 (`:`) 分隔 IP 和端口。
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Waiting for application startup.
* 如果您直接运行 Uvicorn,则可以使用`--host 0.0.0.0`和`--port 80`,而不是`--bind 0.0.0.0:80`(Gunicorn 选项)。
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Waiting for application startup.
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Application startup complete.
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Application startup complete.
在输出中,您可以看到它显示了每个进程的 **PID** (进程 ID)(它只是一个数字)。
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Application startup complete.
< span style = "background-color:#007166" > < font color = "#D3D7CF" > INFO < / font > < / span > Application startup complete.
你可以看到:
```
* Gunicorn **进程管理器** 以 PID `19499` 开头(在您的情况下,它将是一个不同的数字)。
* 然后它开始`Listening at: http://0.0.0.0:80`。
* 然后它检测到它必须使用 `uvicorn.workers.UvicornWorker` 处的worker类。
* 然后它启动**4个worker**,每个都有自己的PID:`19511`、`19513`、`19514`和`19515`。
Gunicorn 还将负责管理**死进程**和**重新启动**新进程(如果需要保持worker数量)。 因此,这在一定程度上有助于上面列表中**重启**的概念。
尽管如此,您可能还希望有一些外部的东西,以确保在必要时**重新启动 Gunicorn**,并且**在启动时运行它**等。
## Uvicorn with Workers
< / div >
Uvicorn 也有一个选项可以启动和运行多个 **worker进程** 。
////
然而,到目前为止,Uvicorn 处理worker进程的能力比 Gunicorn 更有限。 因此,如果您想拥有这个级别(Python 级别)的进程管理器,那么最好尝试使用 Gunicorn 作为进程管理器。
//// tab | `uvicorn`
无论如何,您都可以像这样运行它 :
如果您更想要直接使用 `uvicorn` 命令:
< div class = "termy" >
< div class = "termy" >
@ -151,13 +105,15 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
< / div >
< / div >
////
这里唯一的新选项是 `--workers` 告诉 Uvicorn 启动 4 个工作进程。
这里唯一的新选项是 `--workers` 告诉 Uvicorn 启动 4 个工作进程。
您还可以看到它显示了每个进程的 **PID** ,父进程(这是 **进程管理器** )的 PID 为`27365`,每个工作进程的 PID 为:`27368`、`27369`, `27370` 和`27367`。
您还可以看到它显示了每个进程的 **PID** ,父进程(这是**进程管理器**)的 PID 为`27365`,每个工作进程的 PID 为:`27368`、`27369`, `27370` 和`27367`。
## 部署概念
## 部署概念
在这里,您了解了如何使用 **Gunicorn** (或 Uvicorn)管理 **Uvicorn 工作进程**来**并行**应用程序的执行,利用 CPU 中的 **多核** ,并 能够满足**更多 请求**。
在这里,您学习了如何使用多个**工作进程(workers)**来让应用程序的执行**并行化**,充分利用 CPU 的**多核性能**,并能够处理**更多的 请求**。
从上面的部署概念列表来看,使用worker主要有助于**复制**部分,并对**重新启动**有一点帮助,但您仍然需要照顾其他部分:
从上面的部署概念列表来看,使用worker主要有助于**复制**部分,并对**重新启动**有一点帮助,但您仍然需要照顾其他部分:
@ -170,15 +126,13 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
## 容器和 Docker
## 容器和 Docker
在关于 [容器中的 FastAPI - Docker ](docker.md ){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他 **部署概念** 的策略。
在关于 [容器中的 FastAPI - Docker ](docker.md ){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他**部署概念**的策略。
我还将向您展示 **官方 Docker 镜像** ,其中包括 **Gunicorn 和 Uvicorn worker** 以及一些对简单情况有用的默认配置。
在那里,我还将向您展示如何 **从头开始构建自己的镜像** 以运行单个 Uvicorn 进程(没有 Gunicorn)。 这是一个简单的过程,并且可能是您在使用像 **Kubernetes** 这样的分布式容器管理系统时想要做的事情 。
我将向您展示如何**从零开始构建自己的镜像**,以运行一个单独的 Uvicorn 进程。这个过程相对简单,并且在使用 **Kubernetes** 等分布式容器管理系统时,这通常是您需要采取的方法。
## 回顾
## 回顾
您可以使用**Gunicorn**(或Uvicorn)作为Uvicorn工作进程的进程管理器,以利用**多核CPU**, **并行运行多个进程**。
您可以在使用 `fastapi` 或 `uvicorn` 命令时,通过 `--workers` CLI 选项启用多个工作进程(workers),以充分利用**多核 CPU**,以 **并行运行多个进程**。
如果您要设置**自己的部署系统**,同时自己处理其他部署概念,则可以使用这些工具和想法。
如果您要设置**自己的部署系统**,同时自己处理其他部署概念,则可以使用这些工具和想法。