一、什么是Celery
Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以实现任务的异步处理以及定时任务的处理,它的基本工作流程是:
- 先启动任务执行单元Worker,让它一直监听消息中间件中是否有任务
- 客户端可以发布异步任务和定时任务
- 通过Celery将上述任务添加到消息中间件(可以使用rabbitMQ或者Redis)
- 此时Worker可以监听到中间件中有任务,进行执行任务
- 执行完毕后任务结果就放到Backend中(可以使用Redis或者Mysql)
这里主要讨论在Django中如何使用Celery来执行异步任务和定时任务。
二、Django中执行异步任务
1、环境配置
需要注意的是包之间的兼容性
pip install celery == 4.3.0 pip install eventlet == 0.25.1 pip install redis == 3.2.0
2、创建Django项目
其目录结构如下:
- proj/ - manage.py - proj/ - __init__.py - settings.py - urls.py
3、定义Celery实例
创建celery.py文件,位于proj/proj/celery.py
from __future__ import absolute_import, unicode_literals import os from celery import Celery from django.conf import settings # set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings') app = Celery('proj') # Using a string here means the worker doesn't have to serialize # the configuration object to child processes. # - namespace='CELERY' means all celery-related configuration keys # should have a `CELERY_` prefix. app.config_from_object('django.conf:settings', namespace='CELERY') # Load task modules from all registered Django app configs. app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) @app.task(bind=True) def debug_task(self): print('Request: {0!r}'.format(self.request))
4、导入Celery实例
然后,需要将此上述Celery的实例导入到proj/proj/__init__.py
模块中。这样可以确保在Django启动时加载该应用,以便@shared_task
装饰器将使用该应用:
from __future__ import absolute_import, unicode_literals # This will make sure the app is always imported when # Django starts so that shared_task will use this app. from .celery import app as celery_app __all__ = ('celery_app',)
5、在Django配置文件中配置Celery参数
位于:proj/proj/settings.py
... CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0' # Broker配置,使用Redis作为消息中间件 CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0' # BACKEND配置,这里使用redis CELERY_RESULT_SERIALIZER = 'json' # 结果序列化方案 ...
6、创建异步任务
在每一个app下创建tasks.py文件,如下图所示:
这样Celery会自动发现每一个app下的tasks.py文件,在这个文件中写入的就是需要执行的异步任务,相当于Worker。
# Create your tasks here from __future__ import absolute_import, unicode_literals from celery import shared_task @shared_task def add(x, y): print(x+y) return x + y @shared_task def mul(x, y): return x * y @shared_task def xsum(numbers): return sum(numbers)
7、在Django的视图中添加任务,获取结果
from django.shortcuts import render,HttpResponse from app01.tasks import add,mul # Create your views here. #异步任务 def celery_test(request): #delay相当于将异步任务add加入到Broker task = add.delay(4,22) #从Backend中获取执行任务的结果 res = task.get() print(res) return HttpResponse(task)
8、执行异步任务
上述准备工作已经完毕,此时需要启动一个或多个worker进程来监听Broker是否有任务
#启动Worker celery -A proj worker -l info -P eventlet
此时,已经监听Broker了;当访问对应url,执行celery_test函数,会执行到add.delay相当于将任务添加到Broker,这样在视图中可以操纵异步任务执行的结果了。
三、Django中执行定时任务
1、安装django-celery-beat
pip install django-celery-beat
2、Django配置文件添加django-celery-beat
INSTALLED_APPS = ( ..., 'django_celery_beat', )
3、生成对应的表
python manage.py migrate
此时,可以看到生成的一些表
注意,这些任务会自动从每一个app下的tasks中读取,只要是注册过的(用shared_task装饰过)
定时任务具体的时间需要在上述表中设定好,因为定时任务就是从数据库中这些表中读取的
4、启动定时任务
首先,还是需要启Worker,这与异步任务相同
celery -A proj worker -l info -P eventlet
然后需要再开启一个进程用于监听Broker里面的定时任务,到一定的时间,Worker执行
celery -A proj beat -l info -S django
值得注意的是每添加或修改一个任务,celery beat都需要重启一次