程序中的任务主要有两类需求:
一是视图触发任务:就是当更新一个数据时,需要对其它数据进行汇总,而且汇总的数据量大,这时候,需要分为两个进程来处理,一个进程是把数据更新后返回前端,二个进程是执行汇总任务。所谓视图触发任务,就是只有在需要的时候,根据条件去触发任务。
二是定时触发任务:就是规定确定的时间去触发任务。比如:每周汇总一次,每月汇总一次。这类任务就叫定时触发任务。
任务处理有很多插件,但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秒以后,会自动执行!