celery在Django中的集成使用

繼上回安裝和使用Redis以後,看看如何在Django中使用Celery。Celery是Python開發分佈式任務列隊的處理庫。能夠異步分佈式地異步處理任務,也可定時執行任務等等。一般咱們能夠在Django執行一些比較耗時的任務(例如發郵件)和後臺任務(例如爬蟲和更新服務器緩存)。html

研究發現,在Django中使用有兩種方式:python

1)使用django-celery應用;redis

2)直接使用Celery。mongodb

 

一、Celery方式的選擇

這裏Celery的中間人,我採用Redis。也能夠用Django自身和mongodb等。Celery的中間人你能夠理解爲在Celery執行過程當中的數據支持。保存列隊記錄、執行記錄等等。安裝Redis,可參考Redis在CentOS和Windows安裝過程數據庫

這裏還須要安裝celery-with-redis,執行命令:django

  1. pip install celery-with-redis

該命令會自動安裝redis、celery、kombu、billiard、amqp、vine和celery-with-redis相關庫。json

 

先說說django-celery的方式吧。這種方式就是經過manage.py啓動celery。一般先被提到的方案是不會採用。用pip安裝django-celery,在settings引用djcelery應用。再更新數據庫:緩存

  1. python manage.py makemigrations djcelery
  2. python manage.py migrate djcelery

 

查看數據庫,會發現多了不少相關的表。服務器

 

 

稍稍有些強迫症的我,不能接受這些表髒個人數據庫。另外djcelery還有個用途是在admin後臺動態添加定時任務。這個功能也是比較雞肋,維護不方便並且可能形成各類不可預知的問題。多線程

因此建議直接使用Celery管理Django中的任務。這種方式也是Celery官網推薦的方式,可看官網的示例:Celery官網(Celery 3.x版)

 

二、Django簡單項目準備

這裏我也簡單作一個示例。

首先,確保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 

 

三、Django加入Celery

現打開首頁要執行一個收集訪客數據,發送郵件等操做。這是一個耗時任務,若放在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

 

四、把耗時任務丟給celery處理

上面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並測試

啓動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方法的消息。

相關文章
相關標籤/搜索