对于大规模应用程序来说,将 FastAPI 与同步线程结合使用是一种好的做法吗?

Dan*_*lak 8 python multithreading gil python-multithreading fastapi

我正在使用 FastAPI,非async端点在带有多个工作线程的 Gunicorn 上运行,来自此处uvicorn.workers.UvicornWorker建议的类。Latley,我注意到在我们的应用程序比平时更繁忙的时候,我们的一些端点存在高延迟。我开始调查它,发现我们应用程序中的并发性并没有像我们预期的那样工作。

假设我有一个具有以下端点的 FastAPI 应用程序 (main.py)

app = FastAPI()
logger = logging.getLogger()

@app.get("/")
def root():
    logger.info(f"Running on {os.getpid()}")
    time.sleep(3600)
    return {"message": "Hello World"}
Run Code Online (Sandbox Code Playgroud)

gunicorn使用以下命令运行:

gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
Run Code Online (Sandbox Code Playgroud)

当我向服务器发送五个请求时,除了最后一个请求之外,它们都到达同一个工作线程,而不是在所有工作线程上并行运行:

INFO:root:Running on 643
INFO:root:Running on 643
INFO:root:Running on 643
INFO:root:Running on 643
INFO:root:Running on 642
Run Code Online (Sandbox Code Playgroud)

如果我将端点转换为async,则每个请求都将在不同的工作线程上处理(最后一个请求将被保留)。我知道,当使用非异步端点时,FastAPI 使用 AnyIO 线程来处理请求,最大线程的默认值为 40。当我尝试将此限制降低到 2 个线程时,例如使用此处的建议,只有两个请求正在处理,而其他人正在等待(尽管我还有 4 个工人!)

这很糟糕,因为既没有使用我们所有的资源,又因为同一个工作线程上的 GIL 而遭受 python 线程问题。

有没有办法在不转向端点的情况下克服这些问题async