什么是 Celery
Celery 是一个 分布式任务队列/异步执行框架(Python 生态最常用)。它把“长耗时工作”从 Web/API 进程里剥离出去,交给 Worker 进程在后台执行;消息通过 Broker(RabbitMQ/Redis)传递,执行结果可存到 Result Backend(Redis/DB 等)。它还内置 定时调度器(Beat)、任务编排(chain/group/chord)、重试/限速/超时/优先级等能力。
组成与角色
• Producer(你的应用):发送任务消息到 Broker。
• Broker:消息中转(常用 RabbitMQ、Redis)。
• Worker:消费任务并执行,支持多进程/协程池并发。
• Result Backend:保存任务状态与结果(Redis、DB 等)。
• Beat(可选):周期性投递任务(定时任务)。
• 监控(可选):Flower、Prometheus Exporter 等。
工作原理(一次任务从提交到完成)
1. 提交任务:应用调用 task.delay() / apply_async(),Celery 客户端把“任务名 + 参数 + 选项(倒计时/ETA/重试策略/路由)”序列化后推送到 Broker 指定队列。
2. 拉取执行:Worker 与 Broker 建立订阅,按 prefetch(QoS)拿一批消息,反序列化为 Python 调用并在进程/线程/协程池里执行。
3. 确认与重试:
• ACK 策略:一般“执行成功后再 ACK(acks_late)”,Worker 崩溃时消息会被重新投递(实现“至少一次(at-least-once)”语义)。
• 失败重试:可设置 autoretry_for、max_retries、指数退避等。
4. 状态与结果:Worker 将状态机更新到 Backend(PENDING → RECEIVED → STARTED → RETRY/FAILURE/SUCCESS),客户端或监控可查询。
5. 编排:可把多个任务用 chain(串联)/ group(并行)/ chord(并行后汇总) 组合成流程。
语义保证:Celery 默认 至少一次 投递;因此任务实现需 幂等(可用业务唯一键去重、防重入)。
并发模型与调优要点
• 并发池:prefork(多进程,默认 & 通用)、gevent/eventlet(I/O 密集)、solo(调试)。
• 关键参数:
• --concurrency:并发度(进程/协程数量)
• worker_prefetch_multiplier:每个并发单位预取的任务数(影响公平性与延迟)
• task_acks_late=True:任务成功后 ACK,提高可靠性
• task_time_limit / task_soft_time_limit:硬/软超时
• task_annotations:速率限制(rate limit)
• 队列/路由/优先级:将不同任务打到不同队列,配合 RabbitMQ 优先级队列
• Broker/Backend 选择:重度可靠场景优先 RabbitMQ 做 Broker;结果查询多就用 Redis 做 Backend。
• 安全:序列化用 json/msgpack,避免 pickle(除非可信网络且明白风险)。
• 负载与弹性:–autoscale=MAX,MIN 按负载动态调节并发;多机多 Worker 横向扩展。
最小可运行示例
安装
pip install celery[redis] redis
定义 Celery 与任务(celery_app.py)
from celery import Celery
celery_app = Celery(
"demo",
broker="redis://localhost:6379/0",
backend="redis://localhost:6379/0",
)
@celery_app.task(bind=True, autoretry_for=(Exception,), retry_backoff=True, max_retries=3)
def long_task(x: int):
import time
for i in range(5):
time.sleep(2) # 模拟耗时
self = long_task # 仅为类型提示友好
long_task.update_state(state="PROGRESS", meta={"progress": (i+1)*20})
return {"result": x * 2}
提交与查询(app.py,示例调用者)
from celery_app import celery_app, long_task
from celery.result import AsyncResult
# 提交任务
res = long_task.delay(21) # 或 long_task.apply_async((21,), countdown=10)
print("task_id:", res.id)
# 轮询状态
r = AsyncResult(res.id, app=celery_app)
print(r.state, r.info) # PROGRESS 时 r.info={"progress":...}
print(r.get(timeout=60)) # 等结果(生产上常用异步查询/回调而非阻塞)
启动 Worker
celery -A celery_app.celery_app worker --loglevel=INFO --concurrency=4 \
--hostname=worker1@%h
# 定时任务还需:
# celery -A celery_app.celery_app beat --loglevel=INFO
何时该用 Celery
• Web/API 要立刻响应,把长任务(视频转码、报表、抓取、模型推理等)甩给后台跑。
• 需要 重试、持久化、定时、编排、监控、水平扩展。
• 如果只是轻量异步且不在意持久化/重试,FastAPI 的 BackgroundTasks/asyncio.create_task 也可;但生产和多实例/多机场景推荐 Celery/RQ/Dramatiq(Celery 功能最全)。
实战最佳实践(精炼)
• 幂等:用业务唯一键防重复执行;外部副作用操作要能安全重放。
• 小消息:消息里传引用(ID/URL),大数据放对象存储/DB。
• 超时与限速:task_soft_time_limit+task_time_limit、rate limit 防止雪崩。
• 可观测性:Flower 监控;导出 Prometheus 指标;记录任务输入输出要点。
• 资源隔离:不同任务类型分队列分 Worker;CPU 密集任务可单独机器/进程池。
398

被折叠的 条评论
为什么被折叠?



