如何设计一个具有独立后台计算的fastapi应用程序



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

if __name__ == '__main__':
main()

应用程序的这一部分持续运行,读取数据并进行处理,直到手动中止应用程序。我使用asyncio来运行协同程序。

任务

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

问题

我如何运行main.py的这些后台计算,并仍然使用fastapi和jinja2实现仪表板/网站?

  • 构建文件的最佳实践/架构是什么:后台和fastapi应用程序代码?例如,fastapi中是否有一个初始启动函数,我可以在协同程序中调用后台计算,或者反过来调用
  • 根据您的建议,您将如何调用应用程序

到目前为止我所取得的成就

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

任何建筑概念都值得赞赏。非常感谢。

Fastapi不会运行,因为在它完成计算之前,python解释器无法访问它。您应该独立于主进程启动web应用程序,我强烈建议您使用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使用多处理,这可能会导致过程泄漏,因为uvicorn是自己的工人。

一个好的方法是将on_event装饰器与startup一起使用。唯一剩下的就是使用asyncio.create_task来调用后台任务。只要你不等待它,它就不会阻塞,因此fastapi/uvcorn可以继续为任何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想象成你喜欢的任何一类。Kafka消费、计算等。当然,value只是ClassMyService的一个示例属性。

最新更新