快速且高效地构建API是现代软件开发的一个基础方面。然而,由于数据处理、第三方服务调用或复杂计算等原因,经常会遇到执行时间较长的API端点。面对这样的情况,确保这些长时间运行的任务不会降低用户体验或系统性能至关重要。本博客文章旨在指导您如何在FastAPI中管理长时间运行的任务。
您可以使用Python的async def语法在FastAPI中定义异步端点,这有助于I/O绑定操作。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
# 执行一个长时间运行的任务
return {"message": "done"}
FastAPI允许您运行可以在响应已发送后继续处理的后台任务。
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def long_running_task():
# 执行一个长时间运行的任务
pass
@app.get("/")
async def read_root(background_tasks: BackgroundTasks):
background_tasks.add_task(long_running_task)
return {"message": "任务正在后台运行"}
对于特别长时间运行的任务,您可以将它们卸载到像Celery这样的任务队列。
from fastapi import FastAPI
from celery import Celery
app = FastAPI()
celery_app = Celery('tasks', broker='pyamqp://guest@localhost//')
@celery_app.task
def long_running_task():
# 执行一个长时间运行的任务
pass
@app.get("/")
def read_root():
long_running_task.apply_async()
return {"message": "任务正在后台运行"}
一旦任务被卸载或变为异步,通知用户其完成状态是必要的。以下是实现这一目标的一些策略:
服务端:
from fastapi import FastAPI
from some_task_queue import some_task_queue
app = FastAPI()
@app.post("/start_task/")
def start_task():
task_id = some_task_queue.enqueue("long_running_task")
return {"task_id": task_id}
@app.get("/get_result/{task_id}")
def get_result(task_id: str):
result = some_task_queue.get_result(task_id)
return {"result": result}
客户端:
async function startAndPollTask() {
const response = await fetch('/start_task/');
const task = await response.json();
let result;
do {
const resultResponse = await fetch(`/get_result/${task.task_id}`);
result = await resultResponse.json();
if (result.is_done) {
break;
}
await new Promise(resolve => setTimeout(resolve, 2000));
} while(true);
console.log("Final result:", result);
}
服务端:
from fastapi import FastAPI, BackgroundTasks
import requests
app = FastAPI()
def long_running_task(callback_url):
# 执行长时间的任务
result = "some_result"
requests.post(callback_url, json={"result": result})
@app.post("/start_task/")
async def start_task(background_tasks: BackgroundTasks, callback_url: str):
background_tasks.add_task(long_running_task, callback_url)
return {"status": "任务已开始"}
```
3. WebSockets
您可以在客户端和服务器之间建立WebSocket连接,以在任务完成时发送结果。
服务端:
from fastapi import FastAPI, WebSocket
app = FastAPI()
@app.websocket(“/ws/”)
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
# 长时间运行的任务
result = “some_result”
await websocket.send_json({“result”: result})
客户端:
const socket = new WebSocket(‘ws://localhost:8000/ws/’);
socket.addEventListener(‘message’, function(event) {
const result = JSON.parse(event.data);
console.log(“Received result:”, result);
});
4. 服务器推送事件(SSE)
SSE允许服务器通过单个HTTP连接发送更新和最终结果。
服务端:
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
@app.get(“/task_status/”)
def get_status():
def event_stream():
# 长时间运行的任务
result = “some_result”
yield f"data: {result}\n\n"
return StreamingResponse(event_stream(), media_type=“text/event-stream”)
```
客户端:
const eventSource = new EventSource('/task_status/');
eventSource.onmessage = function(event) {
const result = event.data;
console.log("Received result:", result);
};
长时间运行的任务在API设计中可能会带来挑战,但FastAPI提供了各种功能和技巧来有效地处理它们。无论是异步编程、后台任务,还是像Celery、Webhooks和WebSockets这样的高级策略,您都可以根据API的需求选择合适的方法。遵循这些最佳实践和策略,您可以确保长时间运行的任务得到有效管理,而不会损害用户体验或系统性能。
英文版
AI日新月异,但是万丈高楼拔地起,离不开良好的基础。您是否有兴趣了解人工智能的原理和实践? 不要再观望! 我们关于 AI 原则和实践的书是任何想要深入了解 AI 世界的人的完美资源。 由该领域的领先专家撰写,这本综合指南涵盖了从机器学习的基础知识到构建智能系统的高级技术的所有内容。 无论您是初学者还是经验丰富的 AI 从业者,本书都能满足您的需求。 那为什么还要等呢?
人工智能原理与实践 全面涵盖人工智能和数据科学各个重要体系经典
北大出版社,人工智能原理与实践 人工智能和数据科学从入门到精通 详解机器学习深度学习算法原理