项目框架目录树:
django_celery
|
├── course # 新建应用
│ ├── admin.py
│ ├── __init__.py
│ ├── migrations
│ ├── models.py
│ ├── tasks.py # 任务模块
│ ├── urls.py # 路由文件
│ └── views.py
├── db.sqlite3
├── django_celery
│ ├── celeryconfig.py # celery配置文件
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
安装依赖包:
pip3 install django-celery
pip3 install redis
第一步:在项目settings.py
同级目录下创建celeryconfig.py
文件保存celery配置信息,内容如下:
import djcelery
from datetime import timedelta
# 加载django中注册的应用中的任务(例如我们此项目中course应用中的tasks.py任务)
djcelery.setup_loader()
# 手动定义queue队列
CELERY_QUEUES = {
# 定时任务队列
'beat_tasks-1': {
'exchange': 'beat_tasks-1',
'exchange_type': 'direct',
'binding_key': 'beat_tasks-1'
},
'beat_tasks-2': {
'exchange': 'beat_tasks-2',
'exchange_type': 'direct',
'binding_key': 'beat_tasks-2',
},
}
# 设置默认队列,不指定任务队列时默认使用普通任务队列
CELERY_DEFAULT_QUEUE = 'work_queue'
# 导入应用中任务文件
CELERY_IMPORTS = (
'course.tasks',
)
# 有些情况下可以防止死锁
CELERYD_FORCE_EXECV = True
# 设置并发的worker数量
CELERYD_CONCURRENCY = 4
# 设置失败允许重试
CELERYD_ACKS_LATE = True
# 每个worker最多执行100个任务被销毁,可以防止内存泄漏
CELERYD_MAX_TASKS_PER_CHILD = 100
# 单个任务的最大运行时间,超时会被杀死
CELERYD_TASK_TIME_LIMIT = 12 * 30
# 定时任务
CELERYBEAT_SCHEDULE = {
'task1': {
'task': 'course-task', # 任务名
'schedule': timedelta(seconds=10), # 设置每10秒执行一次任务
# 'args': (10, 100) # 任务函数传参
'options': {
'queue': 'beat_tasks-1' # 指定任务队列
}
},
'task2': {
'task': 'course-task', # 任务名
'schedule': timedelta(seconds=10), # 设置每10秒执行一次任务
# 'args': (100, 1000) # 任务函数传参
'options': {
'queue': 'beat_tasks-2' # 指定任务队列
}
}
}
第二步:在项目settings.py
配置文件中添加以下内容
# 注册应用中添加我们的course应用和要使用的异步队列应用djcelery
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djcelery', # 注册djcelery
'course', # 注册我们的
)
# 导入celery配置信息
from .celeryconfig import *
# 以下配置可以放在celeryconfig.py文件中,但为了方便配置,放在settings文件中更好
BROKER_BACKEND = 'redis'
BROKER_URL = 'redis://localhost:6379/1'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/2'
第三步:在项目跟路由配置文件urls.py
文件中配置我们course应用路由:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
# 当访问地址为http://127.0.0.1:8000时对应到我们course应用路由
url(r'', include('course.urls', namespace='course')),
]
第四步:在course
应用的urls.py
文件中,定义视图处理函数路由
from django.conf.urls import url
from .views import do # 导入视图处理函数
urlpatterns = [
# 当访问地址为http://127.0.0.1:8000/do时,对应到course应用中views.py文件中的视图处理函数do
url(r'^do/', do, name='do'), # 为视图函数添加访问路由
]
第五步:在应用中创建tasks.py
任务文件,测试内容如下:
import time
from celery.task import Task
class CourseTask(Task):
# 给任务起名字
name = 'course-task'
def run(self, *args, **kwargs):
print("start course task")
# 模拟耗时
time.sleep(4)
print("args={}, kwargs={}".format(args, kwargs))
print("end course task")
第六步:在course
应用views.py
视图文件中定义视图函数,在视图函数中调用任务
from django.http import JsonResponse
from django.shortcuts import render
from .tasks import CourseTask
def do(request):
# 执行异步任务
print('start do request')
# 调用任务
CourseTask.delay()
# apply_async() 方法可以直接传参并且指定任务队列,使用更方便
# CourseTask.apply_async(args=('hello',), queue=('work_queue'))
print('end do request')
return JsonResponse({'result': 'OK'})
说明:在任务函数中,我们模拟了4秒的延迟,正常情况下,我们访问该视图处理函数时执行到任务调用将会等待4秒,直到任务模块完成,才会继续向下执行,但我们使用了celery异步任务队列,此处将不会阻塞,直接返回response信息。
第七步:启动任务队列
# 由于定时任务发送给了两个不同的队列,因此worker队列必须同时监听这两个队列,来进行消费
python3 manage.py celery worker -l info -n workerA.%h -Q beat_tasks-1
python3 manage.py celery worker -l info -n workerA.%h -Q beat_tasks-2
- 注意点:
如果使用supervisor进行管理时,启动命令应该如下(注意是两个%号):
python3 manage.py celery worker -l info -n workerA.%%h -Q beat_tasks-1
第八步:触发定时任务
python3 manage.py celery beat -l info
第九步:启动django项目
python3 manage.py runserver
第九步:打开浏览器访问地址http://127.0.0.1:8000/do
说明:我们在任务函数中设置的4秒延迟并没有阻塞我们任务函数后面的代码执行,当我们回车后直接返回了json数据。
使用flower管理监控celery任务
(1)安装依赖包flower
pip3 install flower
(2)启动
django manage.py celery flower
(3)在浏览器中查看
http://127.0.0.1:5555
(4)为了安全起见,通常启动时设置账号密码
django manage.py celery flower --basic_auth=用户名:密码