如何设计一个后台独立计算的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?
- 构建文件的最佳 practice/architecture 是什么:背景和 fastapi 应用程序代码?例如fastapi 中是否有一个初始启动函数,我可以在其中调用协程或其他方式调用后台计算?
- 根据您的建议,您将如何调用该应用程序?
到目前为止我取得了什么
我可以 运行 没有任何 fastapi 代码的主应用程序。我可以 运行 没有后台任务的仪表板。两者都可以独立工作。但是 fastapi 没有 运行,当我将它的代码添加到具有后台计算的主应用程序时。 (怎么可能?!?我只能调用主应用程序或 fastapi 应用程序。)
欢迎任何架构概念。
谢谢。
Fastapi 不会 运行 因为 python 解释器在完成您的计算之前无法访问它。你应该独立于主进程启动你的网络应用程序,我强烈建议你使用 docker-compose
。
正如 fastapi 所建议的那样,您应该使用 Dramatiq
或 Celery
来处理大量的后台任务,或者您可以 运行 在 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 的示例属性。
我创建了一个 python 主应用程序 main.py,我用 uvicorn main.main --reload
调用它。当然是 运行 下面的代码...
if __name__ == '__main__':
main()
应用程序的那部分 运行 不断地读取数据并对其进行处理,直到应用程序被手动中止。我使用 asyncio
到 运行 协程。
任务
我想在上面构建一个小型 html 仪表板,可以显示不断计算的数据。
问题
我怎样才能 运行 main.py 的这些后台计算并仍然使用 fastapi 和 jinja2 实现 dashboard/website?
- 构建文件的最佳 practice/architecture 是什么:背景和 fastapi 应用程序代码?例如fastapi 中是否有一个初始启动函数,我可以在其中调用协程或其他方式调用后台计算?
- 根据您的建议,您将如何调用该应用程序?
到目前为止我取得了什么
我可以 运行 没有任何 fastapi 代码的主应用程序。我可以 运行 没有后台任务的仪表板。两者都可以独立工作。但是 fastapi 没有 运行,当我将它的代码添加到具有后台计算的主应用程序时。 (怎么可能?!?我只能调用主应用程序或 fastapi 应用程序。)
欢迎任何架构概念。 谢谢。
Fastapi 不会 运行 因为 python 解释器在完成您的计算之前无法访问它。你应该独立于主进程启动你的网络应用程序,我强烈建议你使用 docker-compose
。
正如 fastapi 所建议的那样,您应该使用 Dramatiq
或 Celery
来处理大量的后台任务,或者您可以 运行 在 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 的示例属性。