Reputation: 133
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
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
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:
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
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