如何设计一个后台独立计算的fastapi app?

how to design a fastapi app with independent background computation?

我创建了一个 python 主应用程序 main.py,我用 uvicorn main.main --reload 调用它。当然是 运行 下面的代码...

if __name__ == '__main__':
    main()

应用程序的那部分 运行 不断地读取数据并对其进行处理,直到应用程序被手动中止。我使用 asyncio 到 运行 协程。

任务

我想在上面构建一个小型 html 仪表板,可以显示不断计算的数据。

问题

我怎样才能 运行 main.py 的这些后台计算并仍然使用 fastapi 和 jinja2 实现 dashboard/website?

到目前为止我取得了什么

我可以 运行 没有任何 fastapi 代码的主应用程序。我可以 运行 没有后台任务的仪表板。两者都可以独立工作。但是 fastapi 没有 运行,当我将它的代码添加到具有后台计算的主应用程序时。 (怎么可能?!?我只能调用主应用程序或 fastapi 应用程序。)

欢迎任何架构概念。 谢谢。

Fastapi 不会 运行 因为 python 解释器在完成您的计算之前无法访问它。你应该独立于主进程启动你的网络应用程序,我强烈建议你使用 docker-compose。 正如 fastapi 所建议的那样,您应该使用 DramatiqCelery 来处理大量的后台任务,或者您可以 运行 在 compose 服务中分离服务,例如:

# background.py
if __name__ == '__main__':
    main()

# main.py
app = FastAPI()

docker-compose.yml:


services:
  web-app-interface:
    command: uvicorn main.main ...
  my-daemon:
    command: python background.py

您可以让它们与消息代理通信,例如 RabbitMQ 等。 永远不要对 uvicorn 使用多处理,它会导致进程泄漏,bcz uvicorn 规则它是自己的工人。

一个好的方法是将 on_event 装饰器与 startup 一起使用。唯一剩下的就是使用 asyncio.create_task 调用后台任务。只要您不等待它,它就不会阻塞,因此 fastapi/uvicorn 可以继续为任何 http 请求提供服务。

my_service = MyService()

@app.on_event('startup')
async def service_tasks_startup():
    """Start all the non-blocking service tasks, which run in the background."""
    asyncio.create_task(my_service.start_processing_data())

另外,话说回来,任何请求都可以消费这个后台服务的数据。

@app.get("/")
def root():
    return my_service.value

MyService 视为您喜欢的任何 class。 Kafka 消费、计算等。当然,value 只是 Class MyService 的示例属性。