celery在Django中的集成使用

继上回安装和使用Redis以后,看看如何在Django中使用Celery。Celery是Python开发分布式任务列队的处理库。能够异步分布式地异步处理任务,也可定时执行任务等等。一般咱们能够在Django执行一些比较耗时的任务(例如发邮件)和后台任务(例如爬虫和更新服务器缓存)。html

研究发现,在Django中使用有两种方式:python

1)使用django-celery应用;redis

2)直接使用Celery。mongodb

 

一、Celery方式的选择

这里Celery的中间人,我采用Redis。也能够用Django自身和mongodb等。Celery的中间人你能够理解为在Celery执行过程当中的数据支持。保存列队记录、执行记录等等。安装Redis,可参考Redis在CentOS和Windows安装过程数据库

这里还须要安装celery-with-redis,执行命令:django

  1. pip install celery-with-redis

该命令会自动安装redis、celery、kombu、billiard、amqp、vine和celery-with-redis相关库。json

 

先说说django-celery的方式吧。这种方式就是经过manage.py启动celery。一般先被提到的方案是不会采用。用pip安装django-celery,在settings引用djcelery应用。再更新数据库:缓存

  1. python manage.py makemigrations djcelery
  2. python manage.py migrate djcelery

 

查看数据库,会发现多了不少相关的表。服务器

 

 

稍稍有些强迫症的我,不能接受这些表脏个人数据库。另外djcelery还有个用途是在admin后台动态添加定时任务。这个功能也是比较鸡肋,维护不方便并且可能形成各类不可预知的问题。多线程

因此建议直接使用Celery管理Django中的任务。这种方式也是Celery官网推荐的方式,可看官网的示例:Celery官网(Celery 3.x版)

 

二、Django简单项目准备

这里我也简单作一个示例。

首先,确保celery和redis已经安装好了,而且已经启动了Redis服务。

另外,有个已经搭建好了Django项目。做为示例,简单project和简单app以下:

 

为了测试,一切从简。views.py写了一个响应方法:

 1 #coding:utf-8
 2 from django.shortcuts import render  3 from django.http import HttpResponse  4  
 5 from .models import Blog  6 import json  7  
 8 def home(request):  9     data = list(Blog.objects.values('caption')) 10     return HttpResponse(json.dumps(data), content_type = 'application/json')

 

django项目的urls.py加了一条首页的url路由设置:

1 #coding:utf-8
2 from django.conf.urls import url 3 from django.contrib import admin 4 from myapp. 5  
6 urlpatterns = [ 7     url(r'^admin/', admin.site.urls), 8     url(r'^$', 'myapp.views.home', name='home') 9 ]

 

运行django项目:

 1 python manage.py runserver 

 

三、Django加入Celery

现打开首页要执行一个收集访客数据,发送邮件等操做。这是一个耗时任务,若放在home处理方法中执行,用户打开首页会很慢。用户体验很差,极可能不会等到页面打开。

一般这个耗时任务能够多线程处理或者异步处理。咱们模拟一个耗时任务,丢给Celery异步处理。

先模拟耗时任务,打开views.py,修改以下:

 1 #coding:utf-8
 2 from django.shortcuts import render  3 from django.http import HttpResponse  4  
 5 from .models import Blog  6 import json  7 import time  8  
 9 def sendmail(email): 10     print('start send email to %s' % email) 11     time.sleep(5) #休息5秒 12     print('success') 13     return True 14  
15 def home(request): 16  #耗时任务,发送邮件 17     sendmail('test@test.com') 18  
19  #其余行为 20     data = list(Blog.objects.values('caption')) 21     return HttpResponse(json.dumps(data), content_type = 'application/json')

如此一来,至少须要再多等待5秒,才能够打开网页。

打开settings.py所在的文件夹,新建celery.py文件。加入以下代码(注意,由于celery-with-django版本限制,我安装的celery版本为3.1.25。可能celery4.x的版本代码不一样):

 1 #coding:utf-8
 2 from django.shortcuts import render  3 from django.http import HttpResponse  4  
 5 from .models import Blog  6 import json  7 import time  8  
 9 def sendmail(email): 10     print('start send email to %s' % email) 11     time.sleep(5) #休息5秒 12     print('success') 13     return True 14  
15 def home(request): 16  #耗时任务,发送邮件 17     sendmail('test@test.com') 18  
19  #其余行为 20     data = list(Blog.objects.values('caption')) 21     return HttpResponse(json.dumps(data), content_type = 'application/json')

 

这个文件还没被加载,接着打开settings.py同个目录下的__init__.py文件。让运行该Django项目的时候,加载该文件配置Celery。修改代码以下:

1 #coding:utf-8
2 from __future__ import absolute_import, unicode_literals 3  
4 #引入celery实例对象 5 from .celery import app as celery_app

 

还需在settings.py中设置celery,尤为是中间人的设置。若不设置中间人,会提示没法链接中间人的错误。在settings.py文件中添加以下设置:

 1 #celery settings  2 #celery中间人 redis://redis服务所在的ip地址:端口/数据库号
 3 BROKER_URL = 'redis://localhost:6379/0'
 4 #celery结果返回,可用于跟踪结果  5 CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
 6  
 7 #celery内容等消息的格式设置  8 CELERY_ACCEPT_CONTENT = ['application/json',]  9 CELERY_TASK_SERIALIZER = 'json'
10 CELERY_RESULT_SERIALIZER = 'json'
11  
12 #celery时区设置,使用settings中TIME_ZONE一样的时区 13 CELERY_TIMEZONE = TIME_ZONE

 

四、把耗时任务丢给celery处理

上面views.py中有个耗时任务sendmail。在myapp应用中新建文件tasks.py,将sendmail方法剪切到该文件中并用定义为celery任务。tasks.py文件以下代码:

 1 #coding:utf-8
 2 from celery.decorators import task  3 import time  4  
 5 @task  6 def sendmail(email):  7     print('start send email to %s' % email)  8     time.sleep(5) #休息5秒  9     print('success') 10     return True

 

在原有的方法上加上celery装饰器task。或者也能够经过前面添加的celery_app给sendmail方法加装饰器:

 1 #coding:utf-8
 2 #myproject是当前django的项目名  3 from myproject import celery_app  4 import time  5  
 6 @celery_app.task  7 def sendmail(email):  8     print('start send email to %s' % email)  9     time.sleep(5) #休息5秒 10     print('success') 11     return True

 

另外原先的views.py修改以下:

 1 #coding:utf-8
 2 from django.shortcuts import render  3 from django.http import HttpResponse  4  
 5 from .models import Blog  6 from .tasks import sendmail #引用tasks.py文件的中sendmail方法  7 import json  8  
 9 def home(request): 10  #耗时任务,发送邮件(用delay执行方法) 11     sendmail.delay('test@test.com') 12  
13  #其余行为 14     data = list(Blog.objects.values('caption')) 15     return HttpResponse(json.dumps(data), content_type = 'application/json')

五、本地启动celery并测试

启动celery以前,确保已经安装redis和启动redis服务,可参考Redis在CentOS和Windows安装过程

本地开发环境运行redis-cli看是否能够正常链接,若不行,再手工执行redis-server命令并保持窗口便可。

 

 

接着,启动celery worker。这个worker是用于异步执行任务的“工做者”。进入manage.py文件所在的目录,执行以下命令:

 1 Celery -A myproject worker -l info 

 

出现以下窗口和消息,则正常执行。

 

 

celery worker会扫描django项目中有哪些task任务,并加入进来。

最后,再启动django服务器。这个你们熟悉的python manage.py runserver。

打开首页,能够发现没有5秒等待当即获得首页内容。查看celery worker,可看到执行sendmail方法的消息。

相关文章
相关标签/搜索