celery四:示例,在django中使用celery---由视图函数触发任务
项目结构:
myproj
/myproj
__init__.py
celery.py
settings.py
/app01
tasks.py
views.py
/app02
tasks.py
views.py
一.在django中发起celery任务
pip install django
pip install celery
1.在项目myproj/myproj中新建celery.py,配置celery app实例:
from __future__ import absolute_import from __future__ import unicode_literals from celery import Celery import os app = Celery("myproj") # 项目名称 # 让django知道环境变量的位置;第二个参数,项目名称.settings os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproj.settings") # 配置celery查找配置的位置:到settings中,找"CELERY_"开头的配置 app.config_from_object("django.conf:settings", namespace="CELERY") # 自动加载,自动查找所有已注册的app下的tasks.py文件中的任务 app.autodiscover_tasks()
2.在项目myproj下的__init_.py文件中,必须添加以下内容:
from __future__ import absolute_import from .celery import app as celery_app __all__ = ['celery_app']
3.在settings中,配置celery的配置:这里配置redis,当然还可配置其它的选项。
在django中配置redis,使用
CELERY_BROKER_URL = "redis://:123456@192.168.10.11" CELERY_RESULT_URL = "redis://:123456@192.168.10.11"
而不是原来的
broker="redis://:123456@192.168.10.11" backend="redis://:123456@192.168.10.11"
4.在各app项目下的tasks.py中,写任务
# app01/tasks.py from __future__ import unicode_literals from celery import shared_task # 注意在djanog中,任务装饰器:不是使用app实例的task方法(@app.task),而是使用celery中的@shared_task装饰任务; # @shared_task @shared_task def add(x, y): print 'running task add......' return x + y @shared_task def mul(x, y): return x * y
5.任务由谁调用:定时任务或视图函数调用,这里使用视图函数调用
配置url:
#myproj/urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^call_celery_func/$', views.call_celery_func), ]
视图函数:
# app01/views.py from django.shortcuts import render from app01 import tasks def call_celery_func(request): # 调用任务仍然使用delay res = tasks.add.delay(5, 999) print("task.add--tasks_id: ", res.task_id) return render(res.task_id)
6.前端,使用ajax请求celery的视图函数。
如果视图函数只返回task_id,那么将立即返回;然后调用另外一个接口去获取执行任务的结果;这样就实现了异步django。
因为celery的执行流程:调用任务tasks.add.delay(3, 5) --->将会立即写入中间件redis数据库中,并立即返回任务id---->worker进程,会再跟中间件redis数据库交互,从中取出任务执行,这里是耗时操作。
我们只需要分两次调用,第一次调用一个接口立即得到任务id;然后再用另外一个接口去获取任务执行的结果,这个接口必须像tornado一样实现回调异步返回或协程异步返回;这就实现了异步返回。
二、在另一台linux服务器上,开启worker进程
如果worker进程,跟发起django任务请求的进程,在同一台服务器上,可以使用同一份代码;
如果worker进程,跟发起django任务请求的进程,则必须在两台服务器上,都要复制一份代码。
因为,worker进程中调用的任务的函数,要有查找函数代码的地方;
因为,在django发起任务请求的时侯,只是将任务的函数名称保存到redis中;worker执行端,需要在worker所在的服务器上,查找 此函数名对应的代码,才能执行此函数。发起任务和接收任务的连接,靠的是中间件redis数据库;一个是向redis存放数据,一个是向redis数据库取数据。
celery -A myproj worker -l info
三、获取任务执行的结果
任务执行的结果,保存在中间件redis数据库中,可以在redis数据库中查找到任务执行结果。
在代码中,获取任务执行结果:
直接使用在django中发起任务时,接收任务结果的res,调用res.get()方法,获取结果。
from celery.result import AsyncResult res = AsyncResult(任务id) while res.ready(): time.sleep(0.1)
res.get()
如果,我们使用第二段中的方法(下面的方法),不等待任务执行结束,立即返回任务id,那么得不到任务执行的结果
def call_celery_func(request): res = tasks.add.delay(5, 999) return render(res.task_id)
此时,只能根据任务id,去获取任务执行的结果,方法:
from celery.result import AsyncResult res = AsyncResult(id="任务id")
while res.status == "SUCCESS":
time.sleep(0.1) res.get()
不管使用哪种方法获取任务的执行结果,都是从中间件redis数据库中,去获取。
posted on 2018-08-18 21:58 myworldworld 阅读(621) 评论(0) 收藏 举报