第一步安装
pip install celery
选择消息代理
使用于生产环境的消息代理有 RabbitMQ 和 Redis, 官方推荐 RabbitMQ
Celery 序列化
在客户端和消费者之间传输数据需要 序列化和反序列化. Celery 支出的序列化方案如下所示:
五. 安装,配置与简单示例
Celery 配置参数汇总
代码示例 :
注意上半部分是异步任务的配置 如果要配置定时任务才加下面注释掉的部分
定时任务不一定要写在 Django 的视图方法中,您可以使用 Celery 或其他任务调度工具来定时执行任务,而不必依赖于视图方法。
# Broker配置,使用Redis作为消息中间件
BROKER_URL = 'redis://:6379/0'
# BACKEND配置,这里使用redis 指定 Redis 连接地址,用于存储任务结果
CELERY_RESULT_BACKEND = 'redis://6379/0'
# celery内容等消息的格式设置,默认json
CELERY_ACCEPT_CONTENT = ['application/json', ]
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
# 任务结果过期时间,秒
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
# 时区配置
CELERY_TIMEZONE='Asia/Shanghai'
# 指定导入的任务模块,可以指定多个
CELERY_IMPORTS = (
# 'bbs.tasks',
'echartsapp.tasks',
)
CELERY_TASK_TIME_LIMIT = 5
# 定义定时任务的配置
# CELERY_BEAT_SCHEDULE = {
# 'sync-redis-to-mysql': {
# # 'task': 'bbs.tasks.sync_redis_to_mysql', # 替换为您的任务函数路径
# # 'schedule': crontab(minute=0, hour=0), # 在每天的午夜触发任务
# 'task': 'bbs.tasks.scheduled_task',
# # 每10s执行一次
# 'schedule': timedelta(seconds=10),
# },
# }
配置celery.py 在根项目路径下
import os
import django
from celery import Celery
from django.conf import settings
# 设置系统环境变量,安装django,必须设置,否则在启动celery时会报错
# djangotest 是当前项目名
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoTest.settings')
#实例化一个celery类
django.setup()
celery_app = Celery('djangoTest')
#指定配置文件的位置
celery_app.config_from_object('django.conf:settings', namespace='CELERY')
#自动从settings的配置INSTALLED_APPS中的应用目录下加载 tasks.py
celery_app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
配置init.py 在根项目路径下 一般也可不配这个
from __future__ import absolute_import, unicode_literals
from .celery import celery_app
__all__ = ['celery_app']
调用任务的方法 :
1. delay
task.delay(args1, args2, kwargs=value_1, kwargs2=value_2)
2. apply_async
delay 实际上是 apply_async 的别名, 还可以使用如下方法调用, 但是 apply_async 支持更多的参数:
task.apply_async(args=[arg1, arg2], kwargs={key:value, key:value})
支持的参数 :
countdown : 等待一段时间再执行.
add.apply_async((2,3), countdown=5)
eta : 定义任务的开始时间.
add.apply_async((2,3), eta=now+tiedelta(second=10))
expires : 设置超时时间.
add.apply_async((2,3), expires=60)
retry : 定时如果任务失败后, 是否重试.
add.apply_async((2,3), retry=False)
retry_policy : 重试策略.
max_retries : 最大重试次数, 默认为 3 次.
interval_start : 重试等待的时间间隔秒数, 默认为 0 , 表示直接重试不等待.
interval_step : 每次重试让重试间隔增加的秒数, 可以是数字或浮点数, 默认为 0.2
interval_max : 重试间隔最大的秒数, 即 通过 interval_step 增大到多少秒之后, 就不在增加了, 可以是数字或者浮点数, 默认为 0.2 .
自定义发布者,交换机,路由键, 队列, 优先级,序列方案和压缩方法:
task.apply_async((2,2), compression=‘zlib’, serialize=‘json’, queue=‘priority.high’, routing_key=‘web.add’, priority=0, exchange=‘web_exchange’)
编写任务
一般是在 app 下新建一个 task 文件,里面写周期性的任务,使用 @app.task 装饰器定义。
task.py: 在你的app下
@shared_task
def sync_redis_to_mysql(key,pk):
# 获取 Redis 中的计数值
# celery - A djangoTest beat
redis_count = cache.get(key) or 0
dbv = key.split('-')[0]
# 获取数据库中的值
# view_count = serializer.data.get('view_count')
db_count = TTopic.objects.values_list(dbv, flat=True).get(article_id=pk)
# 将 Redis 计数值加到数据库中
TTopic.objects.filter(pk).update(dbv=db_count + redis_count)
# 清空 Redis 中的计数值
cache.delete(key)
异步调用任务
Celery调用异步任务有三个方法:
app.send_task 不是很常用
# tasks.py
from celery import Celery
app = Celery()
def add(x,y):
return x+y
app.send_task('tasks.add',args=[10,20])
# 参数基本和apply_async函数一样# 但是send_task在发送的时候是不会检查tasks.add函数是否存在的,即使为空也会发送成功,所以celery执行是可能找不到该函数报错;
Task.delay
def inset(request):
test.delay(args=[3,5])
return HttpResponse('ok')
Task.delay(参数1, 参数1, 键值, kwargs2=value_2)
Task.apply_async 与delay类似,但支持更多参数
def inset(request):
result = test.apply_async(args=[4,5])
return HttpResponse('ok')
task.apply_async(args=[arg1, arg2], kwargs={key:value, key:value})
测试:当你通过浏览器访问链接时,你根本感受不到2s的延迟,页面可以秒开,同时你会发现终端的输出显示任务执行成功。
使用 apply_async 方法调用 test 任务还能打印任务 id 和任务 status
def inset(request):
result = test.apply_async(args=[3,5])
print(result.id)
print(result.status)
return HttpResponse('ok')
执行任务
在使用 Celery 执行异步任务时,通常需要先运行 Celery 服务(工作进程)然后再运行您的项目。这是因为 Celery 工作进程会独立运行并监听队列,以便随时处理异步任务。
下面是一般的步骤:编写任务,
-
先运行 Celery 服务:
celery -A your_project_name worker --loglevel=info
这将启动 Celery 工作进程,它会一直运行,等待执行异步任务。
-
然后运行您的项目:
python manage.py runserver
或者根据您的项目配置方式启动 Django 项目。您的项目运行后,可以通过视图方法或其他方式触发异步任务的执行。
-
如果您有定时任务,还可以启动 Celery Beat 服务来调度这些任务:
celery -A your_project_name beat --loglevel=info
celery -A your_project_name beat --loglevel=info
这将启动 Celery Beat 服务,它将按照预定的时间表执行定时任务。
请注意,Celery 和您的项目是独立运行的,它们之间通过消息队列进行通信。当您的项目触发异步任务时,它会将任务放入消息队列,然后 Celery 工作进程会从队列中获取任务并执行。这种方式可以确保异步任务不会阻塞或影响您的主项目。
更多可查看中文文档
前言 - Celery 中文手册