zoukankan      html  css  js  c++  java
  • celery在Django中的集成使用

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

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

    1)使用django-celery应用;

    2)直接使用Celery。

    1、Celery方式的选择

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

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

    1. pip install celery-with-redis

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

    先说说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版)

    2、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 

    3、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

    4、把耗时任务丢给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')

    5、本地启动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方法的消息。

  • 相关阅读:
    vuejs cli3 env配置文件实践指南
    Nginx的rewrite(地址重定向)剖析
    什么是TCP粘包?怎么解决这个问题
    windows bat批处理语法简析
    BAT文件语法和技巧(bat文件的编写及使用)
    Asyncio之EventLoop笔记
    python struct的使用例子
    redis慢查询笔记
    redis基础操作概念等笔记
    Python实现Dijkstra算法
  • 原文地址:https://www.cnblogs.com/dengshihuang/p/8257547.html
Copyright © 2011-2022 走看看