一、消息持久化机制
1.1 内存任务的风险
FastAPI默认的BackgroundTasks将任务存储在内存中,存在以下局限性:
- 服务器重启导致未执行任务丢失
- 高并发场景下内存压力过大
- 无法实现分布式任务调度
1.2 持久化实现方案
graph TD
A[请求接收] --> B{是否需要持久化}
B -->|是| C[序列化任务]
C --> D[消息队列存储]
D --> E[持久化数据库备份]
B -->|否| F[内存队列]
通过结合 SQLAlchemy 实现任务状态持久化存储:
python
from fastapi import BackgroundTasks, FastAPI
from pydantic import BaseModel
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite:///./tasks.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class AsyncTask(Base):
__tablename__ = "tasks"
id = Column(Integer, primary_key=True)
task_type = Column(String(50))
params = Column(String(500))
is_completed = Column(Boolean, default=False)
retry_count = Column(Integer, default=0)
Base.metadata.create_all(bind=engine)
app = FastAPI()
def persist_task(task_data: dict):
db = SessionLocal()
try:
new_task = AsyncTask(
task_type=task_data["type"],
params=str(task_data["params"]),
retry_count=0
)
db.add(new_task)
db.commit()
return new_task.id
finally:
db.close()
推荐技术栈组合:
python
# 依赖库版本
pydantic==2.5.1
celery==5.3.4
redis==4.5.5
二、ACK确认机制
2.1 消息生命周期模型
sequenceDiagram
participant Client
participant API
participant Queue
participant Worker
Client->>API: 发送请求
API->>Queue: 持久化存储
Queue->>Worker: 消息投递
Worker-->>Queue: ACK确认
Queue->>API: 删除消息
2.2 实现可靠消息处理
在消息处理过程中加入双重确认机制:
python
from typing import Optional
from fastapi import HTTPException
def process_email_task(task_id: int):
db = SessionLocal()
try:
task = db.query(AsyncTask).filter(AsyncTask.id == task_id).first()
if not task:
raise HTTPException(status_code=404, detail="Task not found")
# 第一阶段确认(消息出队)
task.is_locked = True
db.commit()
# 执行具体业务逻辑
send_email(json.loads(task.params))
# 第二阶段确认(完成确认)
task.is_completed = True
db.commit()
except Exception as e:
task.retry_count += 1
db.commit()
raise e
finally:
db.close()
三、生产环境实现方案
3.1 集成Celery+RabbitMQ
python
# celery_config.py
from celery import Celery
celery_app = Celery(
'background_tasks',
broker='pyamqp://user:pass@rabbitmq//',
backend='redis://redis:6379/0',
task_serializer='json',
result_serializer='json',
accept_content=['json']
)
3.2 增强型任务模型
python
from pydantic import Field
class PersistentTask(BaseModel):
payload: dict
queue_name: str = Field(default="default", max_length=20)
priority: int = Field(default=5, ge=1, le=10)
expire_seconds: int = 3600
四、课后Quiz
发现1000+提升效率与开发的AI工具和实用程序:tools.cmdragon.cn/
Q1:如何保证任务在服务器重启后不丢失? A:采用消息队列持久化存储,配置消息的delivery_mode=2,并启用队列的持久化属性
Q2:ACK机制的主要作用是什么? A:确保消息被正确处理后才从队列移除,防止消息丢失
五、常见报错处理
502 Bad Gateway
- 原因:消息队列连接超时
- 解决:
- 检查RabbitMQ服务状态
- 验证网络连接配置
- 增加心跳检测机制
422 Validation Error
- 典型场景:任务模型字段验证失败
- 排查步骤:
- 检查请求体是否符合PersistentTask模型
- 验证priority是否在1-10之间
- 确认expire_seconds是否为整数