Uvicorn 服务器意外关闭

Posted

技术标签:

【中文标题】Uvicorn 服务器意外关闭【英文标题】:Uvicorn server shutting down unexpectedly 【发布时间】:2019-11-23 23:39:33 【问题描述】:

我正在使用由 Uvicorn 服务器提供的 FastAPI 框架。 我的应用程序应该在给定的端点 (/run) 上运行一些耗时的数值计算。为此,我使用了来自 fastAPI 的“background_task”(基本上是来自 Starlette 的“background_task”)。

在运行应用程序时,经过一些名义行为后,服务器由于某种原因而关闭。

应用程序的日志如下所示:

INFO: Started server process [922]
INFO: Waiting for application startup.
DEBUG: None - ASGI [1] Started
DEBUG: None - ASGI [1] Sent 'type': 'lifespan.startup'
DEBUG: None - ASGI [1] Received 'type': 'lifespan.startup.complete'
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
DEBUG: ('10.0.2.111', 57396) - Connected
DEBUG: ('10.0.2.111', 57397) - Connected
DEBUG: ('10.0.2.111', 57396) - ASGI [2] Started
DEBUG: ('10.0.2.111', 57396) - ASGI [2] Received 'type': 'http.response.start', 'status': 200, 'headers': '<...>'
INFO: ('10.0.2.111', 57396) - "GET /run HTTP/1.1" 200
DEBUG: ('10.0.2.111', 57396) - ASGI [2] Received 'type': 'http.response.body', 'body': '<32 bytes>'
DEBUG: ('10.0.2.111', 57396) - ASGI [3] Started
DEBUG: ('10.0.2.111', 57396) - ASGI [3] Received 'type': 'http.response.start', 'status': 404, 'headers': '<...>'
INFO: ('10.0.2.111', 57396) - "GET /favicon.ico HTTP/1.1" 404
DEBUG: ('10.0.2.111', 57396) - ASGI [3] Received 'type': 'http.response.body', 'body': '<22 bytes>'
DEBUG: ('10.0.2.111', 57396) - ASGI [3] Completed

...

DEBUG: ('10.0.2.111', 57396) - Disconnected
... The background task is completed.
DEBUG: ('10.0.2.111', 57396) - ASGI [2] Completed
DEBUG: ('10.0.2.111', 57397) - Disconnected
DEBUG: ('10.0.2.111', 57405) - Connected

...
The application goes on, with requests and completed background tasks.
At some point, during the execution of a background task:

INFO: Shutting down
DEBUG: ('10.0.2.111', 57568) - Disconnected
DEBUG: ('10.0.2.111', 57567) - Disconnected
INFO: Waiting for background tasks to complete. (CTRL+C to force quit)
DEBUG: ('10.0.2.111', 57567) - ASGI [6] Completed
INFO: Waiting for application shutdown.
DEBUG: None - ASGI [1] Sent 'type': 'lifespan.shutdown'
DEBUG: None - ASGI [1] Received 'type': 'lifespan.shutdown.complete'
DEBUG: None - ASGI [1] Completed
INFO: Finished server process [922]

我真的不明白为什么会这样。我不知道要尝试什么来修复它。

我的代码如下所示。

#!/usr/bin/env python3.7
import time
from fastapi import FastAPI, BackgroundTasks
import uvicorn
from starlette.responses import JSONResponse
import my_imports_from_project

analysis_api = FastAPI()

@analysis_api.get("/")
def root():
    return "message": "root"


@analysis_api.get("/test")
def test():
    return "message": "test"

@analysis_api.get("/run")
def run(name: str, background_task: BackgroundTasks):
    try:
        some_checks(name)
    except RaisedExceptions:
        body = "running": False,
                "name": name,
                "cause": "Not found in database"
        return JSONResponse(status_code=400, content=body)
    body = "running": True,
            "name": name
    background_task.add_task(run_analysis, name)
    return JSONResponse(status_code=200, content=body)


if __name__ == "__main__":
    uvicorn.run("api:analysis_api", host="0.0.0.0", log_level="debug")

【问题讨论】:

你试过通过 gunicorn 运行 uvicorn 吗? gunicorn 可能会保持这个过程 我想知道后台任务的完成是否会以某种方式触发关闭请求 关于 gunicorn: * 它发生了同样的事情,但至少 gunicord 重新启动了服务器。关于触发关机的任务: *我不知道,它只是进行计算并将结果保存在数据库中。而且,有些任务成功了,只有一个关闭服务器(所有任务都是平等的) 【参考方案1】:

这就是我解决整个问题的方法。

我认为问题在于我的任务会产生一些进程以执行计算。 因此,我现在使用的是multiprocessing.Process(),而不是使用 FastApi background_task。 这样就解决了。

正如来自 FastApi 的人员所指出的,如果项目变得庞大而复杂,此解决方案可能无法很好地扩展。在这种情况下,强烈建议使用消息队列+任务运行之类的东西(如FastApi site 所建议的那样。

但是,对于小型项目,multiprocessing.Processsubprocess.Popen 的解决方案完全没问题。

【讨论】:

使用外部队列既可以让您控制应用程序实例处理工作中的消费者/订阅者/线程的数量,也可以让您部署可以添加到队列和工作的应用程序的多个实例排队。此外,如果处理它们的实例崩溃,它将启用自动重新启动/恢复排队的工作项。

以上是关于Uvicorn 服务器意外关闭的主要内容,如果未能解决你的问题,请参考以下文章

Fastapi python代码执行速度受uvicorn vs gunicorn部署的影响

有没有办法为 Starlette/Uvicorn 显式设置 MIME 类型?

uvicorn 抑制了 gelf 驱动程序的 python 系统日志

如何使用 Uvicorn 和 asyncio.create_task() 将任务置于后台?

WinSCP 服务器意外关闭网络连接

底层连接被关闭:连接被意外关闭