使用Uvicorn部署docker化的FastAPI应用程序和Tiangolo的Gunicorn+Uvicorn有什么区别?为什么我的结果显示仅使用 Uvicorn 部署时获得的结果比 Gunicorn+Uvicorn 更好?
当我搜索 Tiangolo 的文档时,它说:
您可以使用 Gunicorn 来管理 Uvicorn 并运行多个并发进程。这样,您就可以充分利用并发性和并行性。
由此看来,我是否可以假设使用这个 Gunicorn 会得到更好的结果?
这是我使用 JMeter 进行的测试。我将脚本部署到 Google Cloud Run,结果如下:
使用Python和Uvicorn:
使用Tiangolo的Gunicorn+Uvicorn:
这是我的 Python (Uvicorn) Dockerfile:
FROM python:3.8-slim-buster
RUN apt-get update --fix-missing
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libgl1-mesa-dev python3-pip git
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip3 install -U setuptools
RUN pip3 install --upgrade pip
RUN pip3 install -r ./requirements.txt --use-feature=2020-resolver
COPY . /usr/src/app
CMD ["python3", "/usr/src/app/main.py"]
这是我的 Tiangolo 的 Gunicorn+Uvicorn 的 Dockerfile:
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8-slim
RUN apt-get update && apt-get install wget gcc -y
RUN mkdir -p /app
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN python -m pip install --upgrade pip
RUN pip install --no-cache-dir -r /app/requirements.txt
COPY . /app
您可以从 Tiangolo 的 Gunicorn+Uvicorn 看到错误。是Gunicorn造成的吗?
已编辑。
因此,就我而言,我使用延迟加载方法来加载我的机器学习模型。这是我加载模型的类。
class MyModelPrediction:
# init method or constructor
def __init__(self, brand):
self.brand = brand
# Sample Method
def load_model(self):
pathfile_model = os.path.join("modules", "model/")
brand = self.brand.lower()
top5_brand = ["honda", "toyota", "nissan", "suzuki", "daihatsu"]
if brand not in top5_brand:
brand = "ex_Top5"
with open(pathfile_model + f'{brand}_all_in_one.pkl', 'rb') as file:
brand = joblib.load(file)
else:
with open(pathfile_model + f'{brand}_all_in_one.pkl', 'rb') as file:
brand = joblib.load(file)
return brand
而且,这是我的 API 的端点。
@router.post("/predict", response_model=schemas.ResponsePrediction, responses={422: schemas.responses_dict[422], 400: schemas.responses_dict[400], 500: schemas.responses_dict[500]}, tags=["predict"], response_class=ORJSONResponse)
async def detect(
*,
# db: Session = Depends(deps.get_db_api),
car: schemas.Car = Body(...),
customer_id: str = Body(None, title='Customer unique identifier')
) -> Any:
"""
Predict price for used vehicle.\n
"""
global list_detections
try:
start_time = time.time()
brand = car.dict()['brand']
obj = MyModelPrediction(brand)
top5_brand = ["honda", "toyota", "nissan", "suzuki", "daihatsu"]
if brand not in top5_brand:
brand = "non"
if usedcar.price_engine_4w[brand]:
pass
else:
usedcar.price_engine_4w[brand] = obj.load_model()
print("Load success")
elapsed_time = time.time() - start_time
print(usedcar.price_engine_4w)
print("ELAPSED MODEL TIME : ", elapsed_time)
list_detections = await get_data_model(**car.dict())
if list_detections is None:
result_data = None
else:
result_data = schemas.Prediction(**list_detections)
result_data = result_data.dict()
except Exception as e: # noqa
raise HTTPException(
status_code=500,
detail=str(e),
)
else:
if result_data['prediction_price'] == 0:
raise HTTPException(
status_code=400,
detail="The system cannot process your request",
)
else:
result = {
'code': 200,
'message': 'Successfully fetched data',
'data': result_data
}
return schemas.ResponsePrediction(**result)
Gunicorn 是一个 应用程序服务器,它使用 WSGI 协议与您的 Web 应用程序进行交互。这意味着 Gunicorn 可以为用同步 Web 框架编写的应用程序提供服务,例如 Flask 或 Django(对于 2021 年之前发布的版本更是如此)。 Gunicorn 负责运行 Web 应用程序的多个实例,确保它们正常运行并根据需要重新启动它们,在这些实例之间分发传入请求并与 Web 服务器通信。除此之外,Gunicorn 的速度相当快。为了优化它,我们付出了很多努力。 Gunicorn 本身与 FastAPI 不兼容,因为 FastAPI 使用新鲜的 ASGI 标准。
Uvicorn是一个支持ASGI协议的应用服务器。它还可以选择启动和运行多个工作进程。 然而,Uvicorn 处理工作进程的能力比 Gunicorn 更有限。
Uvicorn 有一个Gunicorn 兼容的工人阶级。 这将允许您在 Gunicorn 中运行 asgi-app!所以,如果你想在那个级别(Python级别)有一个好的进程管理器,你可以使用 Gunicorn 作为你的 asgi-app 的进程管理器!
如果您有一个包含 Kubernetes、Docker Swarm 或其他类似复杂系统的机器集群来管理多台机器上的分布式容器,那么您可能希望在集群级别处理复制,而不是使用进程管理器(例如每个容器中都有 Gunicorn 和工人)。 像 Kubernetes 这样的分布式容器管理系统之一通常具有某种集成的方式来处理容器的复制,同时仍然支持传入请求的负载平衡。全部在集群级别。 在这些情况下,您可能希望从头开始构建 Docker 映像,安装依赖项并运行单个 Uvicorn 进程,而不是使用 Uvicorn 工作程序运行 Gunicorn 之类的东西。