python fastApi 中的全局变量无法正常工作

python global variable in fastApi not working as normal

我有一个简单的 fastApi 演示应用程序,它实现了一个功能: 通过调用名为 changeResponse 的 post api 获得不同的响应 json。 changeResponse api 只是改变了一个全局变量,另一个 api return 不同的响应通过相同的全局 variable.On 本地环境,它工作正常,但响应总是在我之后改变当我在 docker.The 上构建它时调用 changeResponse 一次,代码如下:

from typing import Optional
from fastapi import FastAPI
from util import read_json
import enum

app = FastAPI()

type = "00"
    
@app.post("/changeResponse")
async def handle_change_download_response(param:Optional[str]):
        global type
        type = param
        print("type is "+type)
        return {"success":"true"}

@app.post("/download")
async def handle_download(param:Optional[str]):
    print("get download param: "+param)
    if legalDownload(param):
        print("type is "+type)
        return read_json.readDownloadSuccessRes(type)
    else:
        return read_json.readDownloadFailRes()

def legalDownload(data:str)->bool:
    return True

dockerfile如下:

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7

COPY ./app /app

我除了: 调用 changeResponse 参数为 7,得到 7 的响应, 调用 changeResponse 参数为 8,得到 8 的响应。 我得到了什么: 调用 changeResponse 参数为 7,获取 7 的响应,调用 changeReponse 8,有时响应为 7,有时为 8,无法预测

tiangolo/uvicorn-gunicorn-fastapi 基于 uvicorn-gunicorn-docker image, which by defaults creates multiple workers. Excerpt from gunicorn_conf.py:

default_web_concurrency = workers_per_core * cores

因此,之所以会出现上述情况,是因为请求是由不同的worker(进程)处理的。每个都有自己的全局变量副本

更新:如果你想改变工人的数量,使用以下环境变量:

  • WORKERS_PER_CORE:它会将worker的数量设置为CPU核的数量乘以这个值。
  • MAX_WORKERS:您可以使用它让图像自动计算工人的数量,但要确保它限制在最大值。
  • WEB_CONCURRENCY覆盖工人数量的自动定义。

你可以这样设置:

docker run -d -p 80:80 -e WEB_CONCURRENCY="2" myimage

这些变量和示例的更详细描述here


如果要在worker之间共享数据,注意这个

我已经知道原因了:

the fastapi use uvicorn run the app, and use gunicorn to manage these uvicorn the gunicorn in docker container default starts 2*num_of_core + 1 workers to run these uvicorn,so i assume there are three app in the server,and the request was sented to random worker to handle. that's why the response is random reference:https://docs.gunicorn.org/en/stable/design.html

有同样的问题,在不更换工人的情况下得到解决。

app = FastAPI()

app.type = "00"

我认为这是最好的选择。

非常感谢参考:fastapi/issues/592