Celery 模块详解:方法、工作流程及实际应用
Celery 是一个强大的分布式任务队列系统,用于处理异步任务和定时任务。下面我将详细介绍 Celery 的主要方法、工作流程,并通过实际场景示例说明如何使用。
一、Celery 核心组件和工作流程
工作流程概述
- 客户端 (Producer):创建任务并发送到消息代理
- 消息代理 (Broker):存储任务队列(常用 RabbitMQ, Redis)
- 工作者 (Worker):从队列获取并执行任务
- 结果存储 (Result Backend):可选,存储任务执行结果
Client → Broker → Worker → Result Backend
核心组件
- 应用 (App):Celery 的主要入口点
- 任务 (Task):被异步执行的函数
- 消息代理 (Broker):任务队列
- 工作者 (Worker):执行任务的进程
- 节拍 (Beat):定时任务调度器
二、Celery 主要方法详解
1. 应用初始化方法
from celery import Celery
# 创建Celery应用
app = Celery(
'proj', # 应用名称
broker='redis://localhost:6379/0', # 消息代理URL
backend='redis://localhost:6379/1', # 结果存储URL
include=['proj.tasks'] # 包含的任务模块
)
# 或者通过配置方式
app.conf.update(
broker_url='redis://localhost:6379/0',
result_backend='redis://localhost:6379/1',
task_serializer='json',
accept_content=['json'],
result_serializer='json',
timezone='Asia/Shanghai',
enable_utc=True,
)
2. 任务定义与调用方法
基本任务定义
@app.task
def add(x, y):
return x + y
任务调用方法
# 异步调用(立即返回AsyncResult对象)
result = add.delay(4, 4)
# 同步调用(不推荐,会阻塞)
result = add(4, 4)
# 带选项的任务调用
result = add.apply_async(args=(4, 4), kwargs={},
countdown=10, # 10秒后执行
queue='high_priority',
retry=True,
retry_policy={
'max_retries': 3,
'interval_start': 0,
'interval_step': 0.2,
'interval_max': 0.2,
})
3. 任务状态与结果方法
# 获取任务状态
result.state # 'PENDING', 'STARTED', 'SUCCESS', 'FAILURE', 'RETRY'
# 获取任务结果(阻塞直到结果可用)
result.get(timeout=1)
# 检查任务是否完成
result.ready()
# 获取任务ID
result.id
# 获取异常信息
result.traceback
4. 定时任务 (Periodic Tasks) 方法
from celery.schedules import crontab
app.conf.beat_schedule = {
'add-every-30-seconds': {
'task': 'proj.tasks.add',
'schedule': 30.0, # 每30秒执行一次
'args': (16, 16)
},
'every-monday-morning': {
'task': 'proj.tasks.send_weekly_report',
'schedule': crontab(hour=7, minute=30, day_of_week=1),
},
}
5. 任务路由与队列方法
app.conf.task_routes = {
'proj.tasks.add': {'queue': 'math'},
'proj.tasks.send_email': {'queue': 'email'},
}
# 或者使用装饰器
@app.task(queue='math')
def add(x, y):
return x + y
6. 任务重试方法
@app.task(bind=True, max_retries=3)
def send_email(self, to, subject, body):
try:
email_api.send(to, subject, body)
except email_api.Failure as exc:
# 10秒后重试
raise self.retry(exc=exc, countdown=10)
7. 任务链 (Chaining) 方法
from celery import chain
# 任务链:一个任务完成后将结果传递给下一个任务
chain(add.s(4, 4) | mul.s(8) | div.s(2)).apply_async()
8. 任务组 (Group) 方法
from celery import group
# 并行执行多个任务
group(add.s(i, i) for i in range(10))().get()
9. 任务和弦 (Chord) 方法
from celery import chord
# 组任务完成后执行回调
chord((add.s(i, i) for i in range(10)), xsum.s())().get()
三、实际场景应用示例
场景1:用户注册后发送欢迎邮件
# tasks.py
@app.task(bind=True, max_retries=3)
def send_welcome_email(self, user_id):
try:
user = User.objects.get(id=user_id)
send_mail(
'Welcome to Our Service',
'Thank you for registering!',
'noreply@example.com',
[user.email],
fail_silently=False,
)
except User.DoesNotExist as exc:
self.retry(exc=exc, countdown=60) # 1分钟后重试
except SMTPException as exc:
self.retry(exc=exc, countdown=300) # 5分钟后重试
# views.py
def register(request):
# 处理注册逻辑...
user = create_user(request.POST)
send_welcome_email.delay(user.id) # 异步发送邮件
return HttpResponse('Check your email for confirmation!')
场景2:数据处理流水线
# tasks.py
@app.task
def fetch_data(source):
# 模拟从数据源获取数据
return [1, 2, 3, 4, 5]
@app.task
def process_data(data):
# 模拟数据处理
return [x * 2 for x in data]
@app.task
def save_results(results):
# 模拟保存结果
print(f"Saved results: {results}")
return True
# 使用链式任务处理数据
def start_data_pipeline(source):
chain = (fetch_data.s(source) | process_data.s() | save_results.s())
chain.apply_async()
场景3:定时生成报表
# tasks.py
@app.task
def generate_daily_report():
today = datetime.now().date()
data = get_report_data(today)
report = render_report(data)
save_to_database(report)
send_to_managers(report)
return f"Report generated for {today}"
# celery.py 配置
app.conf.beat_schedule = {
'generate-daily-report': {
'task': 'reports.tasks.generate_daily_report',
'schedule': crontab(hour=23, minute=30), # 每天23:30执行
},
}
场景4:分布式图片处理
# tasks.py
@app.task(bind=True, max_retries=3)
def process_image(self, image_path, operations):
try:
img = Image.open(image_path)
for op in operations:
if op == 'thumbnail':
img.thumbnail((128, 128))
elif op == 'grayscale':
img = img.convert('L')
elif op == 'rotate':
img = img.rotate(90)
output_path = get_output_path(image_path)
img.save(output_path)
return output_path
except IOError as exc:
self.retry(exc=exc, countdown=5)
# 使用
image_path = '/uploads/user123/profile.jpg'
operations = ['thumbnail', 'grayscale']
process_image.delay(image_path, operations)
四、Celery 高级特性
1. 任务撤销
# 发送任务
result = long_running_task.delay()
# 撤销任务
result.revoke()
# 终止正在运行的任务
result.revoke(terminate=True)
2. 任务限流
# 限制任务速率
@app.task(rate_limit='10/m') # 每分钟最多10次
def api_call():
pass
3. 任务超时
@app.task(time_limit=300) # 5分钟超时
def long_running_task():
pass
4. 任务追踪
@app.task(track_started=True)
def tracked_task():
pass
五、最佳实践
-
任务设计原则:
- 保持任务小而专注
- 任务应该是幂等的(可重复执行而不产生副作用)
- 处理所有可能的异常
-
性能优化:
- 使用适当的序列化方法(JSON通常足够)
- 为不同类型任务设置不同队列
- 合理配置工作进程数量
-
监控:
- 使用Flower监控Celery任务
- 集成Sentry捕获任务异常
- 记录任务执行日志
-
部署:
- 使用Supervisor管理Worker进程
- 分离Worker和Beat服务
- 为生产环境配置持久化消息代理
通过以上方法和实际场景示例,您应该能够充分利用Celery来构建高效的异步任务处理系统。Celery的灵活性和强大功能使其成为Python生态系统中处理后台任务的理想选择。