0041 django_celery任务处理(01 视图任务)

  程序中的任务主要有两类需求:

  一是视图触发任务:就是当更新一个数据时,需要对其它数据进行汇总,而且汇总的数据量大,这时候,需要分为两个进程来处理,一个进程是把数据更新后返回前端,二个进程是执行汇总任务。所谓视图触发任务,就是只有在需要的时候,根据条件去触发任务。

  二是定时触发任务:就是规定确定的时间去触发任务。比如:每周汇总一次,每月汇总一次。这类任务就叫定时触发任务。

  任务处理有很多插件,但Celery是处理超大规模的最优插件。我们选用Celery做为任务处理插件。

  本节主要介绍视图触发任务。

  新建一个名为CeleryDemo工程。安装好环境插件。

1 在工程配置目录下(指包含settings.py的目录)创建celery.py文件

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CeleryDemo.settings')  # 设置django环境,CeleryDemo为新建工程名
app = Celery('CeleryDemo') # 为新建工程名
app.config_from_object('django.conf:settings', namespace='CELERY')  # 使用CELERY_ 作为前缀,在settings中写配置
app.autodiscover_tasks()  # 发现任务文件每个app下的task.py 

2 修改工程配置目录下__init__.py文件

from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app

__all__ = ['celery_app'] 

3 修改配置文件

CELERY_BROKER_URL = 'redis://:cgl139@172.17.0.11:5379/26'  # Broker配置,使用Redis作为消息中间件
CELERY_RESULT_BACKEND = 'redis://:cgl139@172.17.0.11:5379/26'  # BACKEND配置,这里使用redis
CELERY_RESULT_SERIALIZER = 'json'  # 结果序列化方案 

4 发布到服务器

  在PyCharm Terminal下发布,进程无法终止,因此在服务器上发布。

  在服务器重建一个虚拟环境,执行:

# &表示可在后台运行,终止后,后台还会运行。
python manage.py runserver 0.0.0.0:81 &
# CeleryDemo表示新建的工程名
celery worker -A CeleryDemo -l debug

  效果如下:

5 编写任务

  在要执行任务的APP目录下,创建tasks.py文件,用于编写任务。

  注:tasks.py必须在APP目录下,而且文件名为能更改。

from __future__ import absolute_import, unicode_literals
from celery import shared_task


@shared_task
def add(x, y):
    print('========================执行add任务')
    return x + y


@shared_task
def mul(x, y):
    print('========================执行mul任务')
    return x * y

5 编写视图

from django.http import JsonResponse
from nucleus import tasks
from django.views import View


# Create your views here.
class Index(View):
    @classmethod
    def get(cls, request):
        res = tasks.add.delay(1, 3)
        # 任务逻辑
        return JsonResponse({'status': 'successful', 'task_id': res.task_id})

6 编写url

from django.contrib import admin
from django.urls import path
from nucleus.views import Index

urlpatterns = [
    path('admin/', admin.site.urls),
    path('Index/', Index.as_view(), ),
]

7 服务器发布

  发布带任务的工程时,启动工程需要在后台运行,反复发布时需要终止之前的进程。常用有以下几个命令:

  &:在命令后空格+&,表示该命令可在后台执行

  lsof -i 81 :用于查看当前端口的任务

  kill -9 进程ID:用于删除当前进程

  确保之前进程已终止,重新发布,在工程目录(包含manage.py目录)下执行:

python manage.py runserver 0.0.0.0:81 &
# 启动工程后,ctrl+c 进入控制台,此时工程在后台运行
celery worker -A CeleryDemo -l debug

8 测试效果

  在浏览器访问Index接口,每访问一次,就可以看到任务执行一次,效果如下:

 9 检验进程

  现在,浏览器每请求一次,任务执行一次,那么,问题来了,是执行完任务,再返回,还是任务和返回同步进行呢?

  我们需要的,并不是先执行完任务再返回,不然,就不需要任务了。那我们改变一下代码任务代码,在任务执行的时候,等20秒,在浏览器请求的时候,是不是能先返回结果,20秒以后,再显示任务执行呢?修改tasks.py

from __future__ import absolute_import, unicode_literals
from celery import shared_task
import time


@shared_task
def add(x, y):
    time.sleep(20)
    print('========================执行add任务')
    return x + y


@shared_task
def mul(x, y):
    print('========================执行mul任务')
    return x * y

  测试结果发现:和我们预料的一样,浏览器请求,马上就收到了返回结果。而任务要20秒以后,会自动执行!

原文地址:https://www.cnblogs.com/dorian/p/12418674.html