Celery學習--- Celery 最佳實踐之與django結合實現異步任務
django 可以輕松跟celery結合實現異步任務,只需簡單配置即可
同步執行和異步執行
註意:即使Celery的任務沒有執行完成,但是已經創建了任務ID。可以利用前臺的定時任務發送Ajax異步請求根據ID查詢結果
項目整合
項目的目錄結構:
項目前提: 安裝並啟動Redis
CeleryTest/settings.py
INSTALLED_APPS = [ ... ‘app01‘, # 註冊app ] MIDDLEWARE = [ ... # ‘django.middleware.csrf.CsrfViewMiddleware‘, ... ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 現添加的配置,這裏是元組,註意逗號 TEMPLATES = [ ... ‘DIRS‘: [os.path.join(BASE_DIR, ‘templates‘)], ] # for celery CELERY_BROKER_URL = ‘redis://192.168.2.105‘, CELERY_BACKEND_URL = ‘redis://192.168.2.105‘, # 用於Celery的返回結果的接收
CeleryTest/urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ url(r‘index/‘, views.Index), url(r‘task_res/‘, views.task_res), ]
app01/views.py
from django.shortcuts import render,HttpResponse from app01 import tasks # Create your views here. # 視圖觸發Celery的用戶請求 def Index(request): print(‘進入Index...‘) res1 = tasks.add(5, 999) res = tasks.add.delay(5, 1000) print("res:", res) return HttpResponse(res) # 前臺通過ID獲取Celery的結果 from celery.result import AsyncResult def task_res(request): result = AsyncResult(id="5cf8ad07-8770-450e-9ccd-8244e8eeed19") # return HttpResponse(result.get()) return HttpResponse(result.status) # 狀態有Pending, Success, Failure等結果
app01/tasks.py 文件名必須為tasks.py
# 文件名必須為tasks.py,Djaogo才能發現Celery from __future__ import absolute_import, unicode_literals from celery import shared_task # Django starts so that the @shared_task decorator (mentioned later) will use it: @shared_task # Django的各個App裏都可以導入這個任務,否則只能在app01這個Django的App內使用 def add(x, y): return x + y @shared_task def mul(x, y): return x * y @shared_task def xsum(numbers): return sum(numbers)
CeleryTest/celery.py 文件名必須為celery.py
from __future__ import absolute_import, unicode_literals import os from celery import Celery # set the default Django settings module for the ‘celery‘ program. os.environ.setdefault(‘DJANGO_SETTINGS_MODULE‘, ‘CeleryTest.settings‘) app = Celery(‘CeleryTest‘) # Using a string here means the worker don‘t have to serialize # the configuration object to child processes. # - namespace=‘CELERY‘ means all celery-related configuration keys # should have a `CELERY_` prefix. app.config_from_object(‘django.conf:settings‘, namespace=‘CELERY‘) # Load task modules from all registered Django app configs. app.autodiscover_tasks() @app.task(bind=True) def debug_task(self): print(‘Request: {0!r}‘.format(self.request))
CeleryTest/__init__.py
from __future__ import absolute_import, unicode_literals # This will make sure the app is always imported when # Django starts so that shared_task will use this app. from .celery import app as celery_app __all__ = [‘celery_app‘]
Django前臺運行結果[獲取到了任務ID]:此時只有Django操作
Django後臺運行結果:此時只有Django操作
上傳文件到Linux服務器【Linux服務器需安裝好Django服務】
需要Ubuntu下安裝Django
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple django
Linux下啟動Celery的worker: 【此時Win7下的Django配合Linux下的Celery執行】
omc@omc-virtual-machine:~/Celery/CeleryTest$ celery -A CeleryTest worker -l info
前臺瀏覽器觸發Django的views請求到Linux的Celery的worker進行結果處理
梳理一下整個的流程:
Win7下的Django配置好了和Celery的整合,連接上Redis。當有請求從瀏覽器發送過來的時候,從URL映射到Django的views裏面,在views裏面調用了tasks.add.delay(5, 1000)此時將任務請求存儲在了Redis裏面。後臺Linux下同樣也放了一份根Win7下同樣的工程[實際上只需要Celery的部分即可],進入Linux下的目錄後啟動Celery的worker,worker從Redis中取出任務去執行。而與此同時Django已經將任務的ID返回給了前臺,前臺可以根據任務ID返回的狀態判斷任務是否完成,完成後從Redis中獲取任務的結果進行頁面渲染即可,從而達到了異步的效果,就是前臺不用直接等待結果的返回,而是根據結果的狀態來獲取最後的結果。
Linux下安裝Django
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple django
問題解決
【20180430】一個由於Django版本和Celery版本差異引起的錯誤,導致一下午很失落,最後誤打誤撞解決,很失望
報錯信息:
KeyError: ‘backend‘
During handling of the above exception, another exception occurred:
settings.py ---Celery的配置錯誤:
# for celery CELERY_BROKER_URL = ‘redis://192.168.2.105‘, CELERY_RESULT_BACKEND = ‘redis://192.168.2.105‘, # 用於Celery的返回結果的接收
問題解決:
settings.py
# for celery CELERY_BROKER_URL = ‘redis://192.168.2.105‘, CELERY_BACKEND_URL = ‘redis://192.168.2.105‘, # 用於Celery的返回結果的接收
Celery學習--- Celery 最佳實踐之與django結合實現異步任務