rookie
rookie

Reputation: 133

Python global variable in FastAPI not working as normal

I have a simple FastAPI demo app which achieve a function: get different response json by calling a post api named changeResponse. The changeResponse api just changed a global variable, another api return different response through the same global variable. On local env, it works correctly, but the response always changes after i just call changeResponse once, when i build this on docker.The code is as follows:

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

the dockerfile is as follows:

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

COPY ./app /app

what i except: call changeResponse param is 7, get response for 7, call changeResponse param is 8, get response for 8. what i get: call changeResponse param is 7, get reponse for 7, call changeReponse 8, sometime the response is 7, sometime is 8, impossible to predict

Upvotes: 12

Views: 27668

Answers (3)

NIK
NIK

Reputation: 1199

Had the same issue and got is fixed without changing the workers.

app = FastAPI()

app.type = "00"

Which I think is the best option.

Ref with many thanks : fastapi/issues/592

Upvotes: 11

alex_noname
alex_noname

Reputation: 32233

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

default_web_concurrency = workers_per_core * cores

Thus, the described situation arises because the request is processed by different workers (processes). Each of which has its own copy of the global variable

Update: If you want to change the count of workers, use the following environment variables:

  • WORKERS_PER_CORE: It will set the number of workers to the number of CPU cores multiplied by this value.
  • MAX_WORKERS: You can use it to let the image compute the number of workers automatically but making sure it's limited to a maximum.
  • WEB_CONCURRENCY Override the automatic definition of number of workers.

You can set it like:

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

A more detailed description of these variables and examples here


If you want to share data between workers, pay attention to this topic.

Upvotes: 11

rookie
rookie

Reputation: 133

I already known why:

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

Upvotes: 0

Related Questions