Fastapi延时任务BackgroundTasks
发布时间:2024-08-24
浏览量: 1715
文章分类: python
先说说背景,之前我用Django开发比较多,所以一直都是用Celery会多一些,也非常方便。这次的FastAPI项目有几个接到请求后需要延伸发送邮件、短信的功能,我第一时间就想到了Celery,但是有个坑点,因为我们的FastAPI项目用了负载均衡,启动了10个web的docker程序,我如果把Celery和web放在一个容器中,就相当于启动了10个Celery,这也不是我想要的结果。但是我研究了一下午也没搞清楚跨网络访问Celery的方法。相关的资料页不多。(关于Fastapi多容器部署Celery等我后面有时间再抽空研究一下。)
这次要说的就是FastAPI自带的一个方便的方法BackgroundTasks。他就在fastapi方法下。
from fastapi import FastAPI,BackgroundTasks
按照上面这样就能直接引入了,非常方便。这个其实没什么好讲的,我直接放个例子看一下就懂了~
from fastapi import FastAPI,BackgroundTasks
import uvicorn
import asyncio
from loguru import logger
app = FastAPI()
async def tasks(kwargs):
"""
异步延时任务,这里可以定义让他干一些别的什么事。
"""
name = kwargs.get("name")
logger.info(f"{name}延时任务开始")
# do something
await asyncio.sleep(10)
logger.info(f"{name}延时任务结束")
count = 1
@app.get("/{page}")
async def root(page:int,background_tasks:BackgroundTasks):
global count
logger.info(f"函数开始运行,请求页码:{page}")
background_tasks.add_task(
tasks,
kwargs={
"name": count
}
)
count += 1
logger.info("函数结束运行")
return {"message": "Hello World"}
if __name__ == '__main__':
uvicorn.run("main:app", host="0.0.0.0", port=8000,reload=True)
在上面的例子中,我们启动项目,然后正常访问http://0.0.0.0:8000/1、http://0.0.0.0:8000/2、http://0.0.0.0:8000/3,可以看看执行记录
2024-08-24 15:01:13.852 | INFO | main:root:25 - 函数开始运行,请求页码:1
2024-08-24 15:01:13.852 | INFO | main:root:33 - 函数结束运行
INFO: 127.0.0.1:50711 - "GET /1 HTTP/1.1" 200 OK
2024-08-24 15:01:13.853 | INFO | main:tasks:14 - 1延时任务开始
2024-08-24 15:01:15.583 | INFO | main:root:25 - 函数开始运行,请求页码:2
2024-08-24 15:01:15.584 | INFO | main:root:33 - 函数结束运行
INFO: 127.0.0.1:50711 - "GET /2 HTTP/1.1" 200 OK
2024-08-24 15:01:15.585 | INFO | main:tasks:14 - 2延时任务开始
2024-08-24 15:01:17.423 | INFO | main:root:25 - 函数开始运行,请求页码:3
2024-08-24 15:01:17.423 | INFO | main:root:33 - 函数结束运行
INFO: 127.0.0.1:50711 - "GET /3 HTTP/1.1" 200 OK
2024-08-24 15:01:17.424 | INFO | main:tasks:14 - 3延时任务开始
2024-08-24 15:01:23.855 | INFO | main:tasks:17 - 1延时任务结束
2024-08-24 15:01:25.586 | INFO | main:tasks:17 - 2延时任务结束
2024-08-24 15:01:27.426 | INFO | main:tasks:17 - 3延时任务结束
在上面的日志中,我们启动项目,然后正常访问,tasks函数是没有阻塞请求的,这样就能比较方便的让请求进来的时候同时去做一些异步请求了,不过需要注意,async/await 问题,避免阻塞。
如果把tasks函数中的await asyncio.sleep(10)换成time.sleep(10)那请求就会立刻阻塞了。你可以自己试试。