繼上回安裝和使用Redis以後,看看如何在Django中使用Celery。Celery是Python開發分佈式任務列隊的處理庫。能夠異步分佈式地異步處理任務,也可定時執行任務等等。一般咱們能夠在Django執行一些比較耗時的任務(例如發郵件)和後臺任務(例如爬蟲和更新服務器緩存)。html
研究發現,在Django中使用有兩種方式:python
1)使用django-celery應用;redis
2)直接使用Celery。mongodb
這裏Celery的中間人,我採用Redis。也能夠用Django自身和mongodb等。Celery的中間人你能夠理解爲在Celery執行過程當中的數據支持。保存列隊記錄、執行記錄等等。安裝Redis,可參考Redis在CentOS和Windows安裝過程。數據庫
這裏還須要安裝celery-with-redis,執行命令:django
該命令會自動安裝redis、celery、kombu、billiard、amqp、vine和celery-with-redis相關庫。json
先說說django-celery的方式吧。這種方式就是經過manage.py啓動celery。一般先被提到的方案是不會採用。用pip安裝django-celery,在settings引用djcelery應用。再更新數據庫:緩存
查看數據庫,會發現多了不少相關的表。服務器
稍稍有些強迫症的我,不能接受這些表髒個人數據庫。另外djcelery還有個用途是在admin後臺動態添加定時任務。這個功能也是比較雞肋,維護不方便並且可能形成各類不可預知的問題。多線程
因此建議直接使用Celery管理Django中的任務。這種方式也是Celery官網推薦的方式,可看官網的示例:Celery官網(Celery 3.x版)
這裏我也簡單作一個示例。
首先,確保celery和redis已經安裝好了,而且已經啓動了Redis服務。
另外,有個已經搭建好了Django項目。做爲示例,簡單project和簡單app以下:
爲了測試,一切從簡。views.py寫了一個響應方法:
1 #coding:utf-8 2 from django.shortcuts import render 3 from django.http import HttpResponse 4 5 from .models import Blog 6 import json 7 8 def home(request): 9 data = list(Blog.objects.values('caption')) 10 return HttpResponse(json.dumps(data), content_type = 'application/json')
django項目的urls.py加了一條首頁的url路由設置:
1 #coding:utf-8 2 from django.conf.urls import url 3 from django.contrib import admin 4 from myapp. 5 6 urlpatterns = [ 7 url(r'^admin/', admin.site.urls), 8 url(r'^$', 'myapp.views.home', name='home') 9 ]
運行django項目:
1 python manage.py runserver
現打開首頁要執行一個收集訪客數據,發送郵件等操做。這是一個耗時任務,若放在home處理方法中執行,用戶打開首頁會很慢。用戶體驗很差,極可能不會等到頁面打開。
一般這個耗時任務能夠多線程處理或者異步處理。咱們模擬一個耗時任務,丟給Celery異步處理。
先模擬耗時任務,打開views.py,修改以下:
1 #coding:utf-8 2 from django.shortcuts import render 3 from django.http import HttpResponse 4 5 from .models import Blog 6 import json 7 import time 8 9 def sendmail(email): 10 print('start send email to %s' % email) 11 time.sleep(5) #休息5秒 12 print('success') 13 return True 14 15 def home(request): 16 #耗時任務,發送郵件 17 sendmail('test@test.com') 18 19 #其餘行爲 20 data = list(Blog.objects.values('caption')) 21 return HttpResponse(json.dumps(data), content_type = 'application/json')
如此一來,至少須要再多等待5秒,才能夠打開網頁。
打開settings.py所在的文件夾,新建celery.py文件。加入以下代碼(注意,由於celery-with-django版本限制,我安裝的celery版本爲3.1.25。可能celery4.x的版本代碼不一樣):
1 #coding:utf-8 2 from django.shortcuts import render 3 from django.http import HttpResponse 4 5 from .models import Blog 6 import json 7 import time 8 9 def sendmail(email): 10 print('start send email to %s' % email) 11 time.sleep(5) #休息5秒 12 print('success') 13 return True 14 15 def home(request): 16 #耗時任務,發送郵件 17 sendmail('test@test.com') 18 19 #其餘行爲 20 data = list(Blog.objects.values('caption')) 21 return HttpResponse(json.dumps(data), content_type = 'application/json')
這個文件還沒被加載,接着打開settings.py同個目錄下的__init__.py文件。讓運行該Django項目的時候,加載該文件配置Celery。修改代碼以下:
1 #coding:utf-8 2 from __future__ import absolute_import, unicode_literals 3 4 #引入celery實例對象 5 from .celery import app as celery_app
還需在settings.py中設置celery,尤爲是中間人的設置。若不設置中間人,會提示沒法鏈接中間人的錯誤。在settings.py文件中添加以下設置:
1 #celery settings 2 #celery中間人 redis://redis服務所在的ip地址:端口/數據庫號 3 BROKER_URL = 'redis://localhost:6379/0' 4 #celery結果返回,可用於跟蹤結果 5 CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' 6 7 #celery內容等消息的格式設置 8 CELERY_ACCEPT_CONTENT = ['application/json',] 9 CELERY_TASK_SERIALIZER = 'json' 10 CELERY_RESULT_SERIALIZER = 'json' 11 12 #celery時區設置,使用settings中TIME_ZONE一樣的時區 13 CELERY_TIMEZONE = TIME_ZONE
上面views.py中有個耗時任務sendmail。在myapp應用中新建文件tasks.py,將sendmail方法剪切到該文件中並用定義爲celery任務。tasks.py文件以下代碼:
1 #coding:utf-8 2 from celery.decorators import task 3 import time 4 5 @task 6 def sendmail(email): 7 print('start send email to %s' % email) 8 time.sleep(5) #休息5秒 9 print('success') 10 return True
在原有的方法上加上celery裝飾器task。或者也能夠經過前面添加的celery_app給sendmail方法加裝飾器:
1 #coding:utf-8 2 #myproject是當前django的項目名 3 from myproject import celery_app 4 import time 5 6 @celery_app.task 7 def sendmail(email): 8 print('start send email to %s' % email) 9 time.sleep(5) #休息5秒 10 print('success') 11 return True
另外原先的views.py修改以下:
1 #coding:utf-8 2 from django.shortcuts import render 3 from django.http import HttpResponse 4 5 from .models import Blog 6 from .tasks import sendmail #引用tasks.py文件的中sendmail方法 7 import json 8 9 def home(request): 10 #耗時任務,發送郵件(用delay執行方法) 11 sendmail.delay('test@test.com') 12 13 #其餘行爲 14 data = list(Blog.objects.values('caption')) 15 return HttpResponse(json.dumps(data), content_type = 'application/json')
啓動celery以前,確保已經安裝redis和啓動redis服務,可參考Redis在CentOS和Windows安裝過程。
本地開發環境運行redis-cli看是否能夠正常鏈接,若不行,再手工執行redis-server命令並保持窗口便可。
接着,啓動celery worker。這個worker是用於異步執行任務的「工做者」。進入manage.py文件所在的目錄,執行以下命令:
1 Celery -A myproject worker -l info
出現以下窗口和消息,則正常執行。
celery worker會掃描django項目中有哪些task任務,並加入進來。
最後,再啓動django服務器。這個你們熟悉的python manage.py runserver。
打開首頁,能夠發現沒有5秒等待當即獲得首頁內容。查看celery worker,可看到執行sendmail方法的消息。