程序中的任務主要有兩類需求:
一是視圖觸發任務:就是當更新一個數據時,需要對其它數據進行匯總,而且匯總的數據量大,這時候,需要分為兩個進程來處理,一個進程是把數據更新后返回前端,二個進程是執行匯總任務。所謂視圖觸發任務,就是只有在需要的時候,根據條件去觸發任務。
二是定時觸發任務:就是規定確定的時間去觸發任務。比如:每周匯總一次,每月匯總一次。這類任務就叫定時觸發任務。
任務處理有很多插件,但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秒以后,會自動執行!