django通过celery添加异步任务

Celery特性:

   异步、分布式、定时任务

Celery架构:

 

异步任务的重要性

大家在做web项目的时候经常会遇到一些耗时的操作, 比如: 发送邮件、发送短信、生成pdf。这些操作在某些情况下需要立即返回结果给用户,但是可以在后台异步执行。

比如用户邮箱注册的时候, 在发送邮件的时候可以先把”已经发送激活邮件到邮箱”返回给用户, 同时把邮件发送任务提交到异步处理线程中。

现在介绍一款python写的专门用于处理异步任务的框架–celery。当然celery能完成的功能远不止异步任务, 还有一个很常用的功能–定时任务

 

Celery简单使用

Celery是通过将代码序列然后传输到中间通信组件,这些组件可以采用任何方式实现, 这里最常用的两种是rabbitmq和redis, 然后celery的后台线程不停的从rabbitmq或者redis中读取这些任务并执行然后返回结果到这些组件,这样就实现了一个异步的功能。

Celery 用redis或者rabbitmq做消息通信,这里redis或者rabbitmq被称为中间人(Broker)Celery 系统可包含多个线程和中间人,以此获得高可用性和横向扩展能力。

 

环境安装:

1、redis安装: apt install redis-server , 安装完成后确认redis服务已启动。

2、celery安装:pip install -U celery[redis]

  该命令会安装celery以及redis开发相关所有的依赖包。安装完成我们可以看到:

这里我们可以看到安装了billiard、pytz、vine、amqp、redis、celery等。

 

Celery常用命令

1、在前台启动worker:  celery worker -A app -l debug

2、在后台启动worker:  celery multi start worker001  -A app -l debug

3、启动任务:  add.delay().get()  

4、查看帮助:  celery --help

 

创建一个简单的任务 tasks.py

from celery import Celery

app = Celery("tasks",
        broker="redis://127.0.0.1",
        backend="redis://127.0.0.1"
)

@app.task
def add(x, y):
        print("runining add..")
        return x + y

在一台Server启动Celery Worker来监听并执行任务

celery worker -A tasks -l debug/info/warning/error/critical

在另一台Server调用任务

>>>from tasks import add
>>>res = add.delay(4,4)
>>>res.ready()
True
>>>res.get() 8

 

在Django项目中使用Celery实现异步任务1

1、在project目录中创建celery.py和tasks.py

from __future__ import absolute_import, unicode_literals
from celery import Celery

app = Celery("proj",
             broker="redis://192.168.20.180",
             backend="redis://192.168.20.180",
             include=['proj.tasks']
)


if __name__ == "__main__":
    app.start()
celery.py
from __future__ import absolute_import, unicode_literals
from .celery import app

@app.task
def mul(x,y):
    return x * y
tasks.py

2、在views.py中调用tasks.py

from proj import tasks


def task_test(request):
    res = tasks.mul.delay(2,5)
    return HttpResponse(res.get())
views.py

3、启动celery

celery worker -A proj -l info    # start celery in the frontend

celery multi start worker001 -A proj -l info    # start celery in the background
View Code

 

在Django项目中使用Celery实现异步任务2

1、修改settings.py

TIME_ZONE = 'Asia/Shanghai'

###配置Broker
BROKER_URL = 'redis://192.168.20.180:6379'
BROKER_TRANSPORT = 'redis'
CELERY_RESULT_BACKEND = 'redis://192.168.20.180'

#CELERY_ACCEPT_CONTENT = ['application/json']
#CELERY_TASK_SERIALIZER = 'json'
#CELERY_RESULT_SERIALIZER = 'json'
#CELERY_TIMEZONE = TIME_ZONE
View Code

2、需要在settings.py同一级目录中创建 celery.py

from __future__ import absolute_import

import os
import django

from celery import Celery
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MxOnline.settings')
django.setup()

app = Celery('MxOnline')

app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
View Code

3、在对应的app目录下创建tasks.py

from MxOnline.celery import app

@app.task
def send_register_email(email, send_type="register"):
    email_record = EmailVerifyRecord()
    if send_type == "update_email":
        code = random_str(4)
    else:
        code = random_str(16)
    email_record.code = code
    email_record.email = email
    email_record.send_type = send_type
    email_record.save()

    email_title = ""
    email_body = ""

    if send_type == "register":
        email_title = "慕学在线网注册激活链接"
        email_body = "请点击下面的链接激活你的账号: http://www.imooc.com/active/{0}".format(code)

        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        if send_status:
            pass
    elif send_type == "forget":
        email_title = "慕学在线网注册密码重置链接"
        email_body = "请点击下面的链接重置密码: http://www.imooc.com/reset/{0}".format(code)

        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        if send_status:
            pass
    elif send_type == "update_email":
        email_title = "慕学在线邮箱修改验证码"
        email_body = "你的邮箱验证码为: {0}".format(code)

        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        if send_status:
            pass
View Code

4、编辑views.py文件完成邮件发送异步调用

#coding:utf-8
    from django.shortcuts import render
    from django.http import HttpResponse

    from .tasks import send_register_email

    def index(request):
        send_register_email.delay()
        return HttpResponse(u"邮件发送成功, 请查收")
View Code

5、启动worker服务,监听执行任务

celery worker -A MxOnline -l info -f logfile
View Code

 

在Django项目中使用Celery实现计划任务

1、install package: pip install django-celery-beat

2、add the "django_celery_beat" module to settings.py "INSTALLED_APPS"

3、apply django database migrate:  python manage.py migrate

4、根据上面《在Django中使用Celery实现异步任务》 编写celery.py(放在sttings.py同一级目录)与tasks.py(放在每个app下)

5、启动celery: celery beat -A proj -S django -l info

6、在Django admin中制定计划任务

 

 注意,经测试,每添加或修改一个任务,celery beat都需要重启一次,要不然新的配置不会被celery beat进程读到.

另外,Celery提供了一个工具flower,将各个任务的执行情况、各个worker的健康状态进行监控并以可视化的方式展现,如下图所示:

 

 

未完待续...

posted @ 2017-06-19 15:22  Vincen_shen  阅读(892)  评论(0)    收藏  举报