(轉)django使用django-celery與celery

一.引言

Django是python語言下的一個比較熱門的Web框架,愈來愈多的企業和開發者使用Django實現本身的Web服務器。在Web服務器開發過程當中,有時候咱們不只僅是要實現Web服務器端和用戶端的簡單邏輯交互,還要實現一些定時任務。舉出如下的例子:  html

  1. 按期刪除或緩存Redis數據庫的記錄
    爲了追求更高的數據庫訪問性能,我把Redis做爲MySql數據庫的緩存。把常訪問的數據放在Redis中,而後定時存儲到Mysql中。而且把過時的Redis數據刪掉.那麼這個時候,就須要定時去完成這個任務。python

  2. 生成報表   
    打個比方,你有一個Web電商服務器,天天用戶都在會在上面購物。爲了很方便的統計出每一個用戶每月的消費金額,你在數據庫中設計了一張月統計報表。而後使用定時任務,在每月的1號進行統計,檢索數據庫,計算出每一個用戶上個月的的消費金額,逐個存儲到月統計報表中。那麼這個生成報表的任務就是定時完成的,也就是前面提到的每月的1號。linux

  3. 定時發送消息
    再如:當你的網站上用戶生日來臨,你但願在他生日那天,給用戶的郵箱發送生日快樂的祝福。那麼這也是定時任務實現的。nginx

上面這些的例子,都是須要定時任務。在Python中,咱們使用的Celery模塊完成這項任務。網絡上關於Celery的博文不少,大多博文的邏輯比較混亂,所以就有了這篇博文。但願讀者讀完有個清晰的認識,而且很好的實戰出來,再也不對celery定時任務有任何的困惑,這是我這篇博文的初衷。web

此篇博文沒有介紹Celery的工做原理,諸如Broker,Worker等等。在實戰以前,這些概念必需要理解清楚。因爲網上已經有不少這樣的內容,我在文章結尾處貼出了一些參考文檔,方便讀者學習。redis


二.Celery,Django和Djcelery

始終明確的是:
Celery是Python的第三方庫,它能夠用因而任何的Python的項目中,由於咱們始終能夠把Celery當作一個獨立的模塊去操縱其它的模塊。所以,咱們能夠在Django項目中使用的Celery,但值得注意的是,在Django中使用Celery的方式有兩種:sql

  1. 僅使用Celery。
  2. 同時使用Celery + djcelery .

方法1: 至關於中Django中加入了一個Celery的任務腳本,爲了操縱Django,所以須要額外在Celery中配置Django環境,才能操做Django的數據庫。數據庫

方法2: 因爲使用了djcelery,能夠在任務中方便的直接操做Django數據庫,並且最終的任務能夠在Django的後臺數據庫中查看和修改相關的任務。
兩種方法的選擇:
從上面的描述看,方法1比方法2少引入一個djcelery模塊,缺點是須要本身配置與Django結合的環境。而方法2,比較方便省心,還能在Django後臺管理本身的任務。所以若是你在Django中使用Celery,我強烈推薦方法2。django

此篇博文講述了使用方法2, 但它們二者本質上是同樣的。兩種方式我都有實踐過, 原先我有打算寫關於姊妹篇(關於方法1)的博文,名字都想好了,叫"Django中使用Celery實現定時任務(不用djcelery)"。可是因爲後來覺得寫了也沒人看,就懶得更新了,再加上後來離職等因素又疏遠了Django後端,因此姊妹篇的計劃就一直擱置了。最初這篇文章發表在CSDN上面,後續收到了一些不錯的反饋,這篇博文就再更新了一次。(可是姊妹篇的計劃卻仍是被我放棄了)。後端

閒聊時間已結束,下面是正文。


三. Django目錄結構

首先記得: pip install django-celery

下面展現了一個Django項目的目錄結構示例:

  • app
      - admin.py
      - views.py
      - urls.py
      - models.py
      - tasks.py
  • pro
      - settings.py
      - urls.py
      - urls.py
      - models.py
  • manage.py

注意,上述目錄中的tasks.py文件是我新建的,放在app的目錄下,整個Celery任務,我只新建了這一個文件。

四. 配置setting.py

爲了設置Celery,咱們須要對setting.py文件進行配置,過程以下:

1.加入djcelery

INSTALLED_APPS = (
    'django.contrib.admin', 'django.contrib.auth', 'djcelery', #此處是新加入的djcelery 'app', )

上述 INSTALLED_APPS中我省略了無關的模塊,注意加入djcelery便可。  

加入 djcelery 後須要執行,migrate遷移,生成數據表。
 

2. 設置celery參數

我在setting.py的文件結尾處,加入了以下的celery參數配置,先貼代碼,再解釋。

import djcelery djcelery.setup_loader() BROKER_URL = 'redis://127.0.0.1:6379/6' CELERY_IMPORTS = ('app.tasks', ) CELERY_TIMEZONE = TIME_ZONE CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' # 下面是定時任務的設置,我一共配置了三個定時任務. from celery.schedules import crontab CELERYBEAT_SCHEDULE = { #定時任務一: 每24小時週期執行任務(del_redis_data) u'刪除過時的redis數據': { "task": "app.tasks.del_redis_data", "schedule": crontab(hour='*/24'), "args": (), }, #定時任務二: 天天的凌晨12:30分,執行任務(back_up1) u'生成日報表': { 'task': 'app.tasks.back_up1', 'schedule': crontab(minute=30, hour=0), "args": () }, #定時任務三:每月的1號的6:00啓動,執行任務(back_up2) u'生成統計報表': { 'task': 'app.tasks.back_up2', 'schedule': crontab(hour=6, minute=0, day_of_month='1'), "args": () }, }

上述代碼釋義:

當djcelery.setup_loader()運行時,Celery便會去查看INSTALLD_APPS下包含的全部app目錄中的tasks.py文件,找到標記爲task的方法,將它們註冊爲celery task。

BROKER_URL = 'redis://127.0.0.1:6379/6'

broker是代理人,它負責分發任務給worker去執行。我使用的是Redis做爲broker,固然你也能夠用其它的broker,好比官方就比較推薦使用RabbitMQ.

有的博客中提到要配置關鍵字:CELERY_RESULT_BACKEND,例如:

CELERY_RESULT_BACKEND = 'amqp://guest@localhost//' #能夠不用寫

我沒有配置這個關鍵字。由於若是沒有配置,此時Django會使用默認的數據庫(也是你指定的orm數據庫),做爲它的結果做爲它的backend。所以你也能夠不用寫,使用Django默認設置的數據庫就很好。

CELERY_IMPORTS = ('app.tasks', ) CELERY_TIMEZONE = TIME_ZONE CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'

上面第一句是導入目標任務文件,第二句是設置時區,第三句表示使用了django-celery默認的數據庫調度模型,任務執行週期都被存在默認指定的orm數據庫中.

更深刻的Celery配置:(http://www.cnblogs.com/ajianbeyourself/p/4950758.html)

from celery.schedules import crontab CELERYBEAT_SCHEDULE = { #定時任務一: 每24小時週期執行任務(del_redis_data) u'刪除過時的redis數據': { "task": "app.tasks.del_redis_data", "schedule": crontab(hour='*/24'), "args": (), },

上面是設置定時的時間配置,關於crontab的具體用法,celery的官方文檔講解的十分詳盡(表格):

http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

我選的三個任務,是我特地挑選的,很是有表明性。第一個是週期任務,它會每隔一個固定時間週期去執行一次相應的task,好比隔1分鐘,隔1小時等; 第二個和第三個都是定時任務,定時在每一個時間點,好比天天的6點,或者定時在每月的1號。
週期任務和定時任務有小小的差異,這也是crontab的強大之處,它同時支持這兩種。

5.Tasks任務

每一個任務本質上就是一個函數,在tasks.py中,寫入你想要執行的函數便可。個人tasks.py以下:我寫的每一個任務又臭又長,所以具體的細節就省略了。

# coding=utf-8 from celery import task @task() def del_redis_data(): # 此處是一個刪除redis數據的操做。具體略過 @task() def back_up1(): # 此處是一個備份到日報表的操做。具體略過 @task() def back_up2(): # 此處是一個生成統計報表的操做。具體略過

若是讀者須要本身實現一個定時任務,那麼上述的task函數必然要本身去定義,我只提供了參考。我上面的三個任務,分別對應了setting.py文件的CELERYBEAT_SCHEDULE的三個定時配置。

要記住的是,任務只是一個函數,這個函數何時調用,取決你在setting.py中的配置。

6.啓動定時任務

登陸到Django後臺,能夠看到後臺數據庫中看到有任務的參數,效果圖暫略。
而後啓動終端,切換到Django項目的根目錄下,運行:

python manage.py runserver # 啓動web服務 python manage.py celery worker -l info # 啓動celery woker

這條命令用於啓動worker, worker本質上執行任務的線程,就是一個幹苦力的工人。

python manage.py celery beat -l info # 啓動beat, 執行定時任務.(原博客在此處有錯誤,已經修改。提示:最新的django-celery匹配celery<4.0,>=3.1.15版本。)python manage.py celery beat -l infobeat

上面這條任務用於啓動beater,它就像一個領導,負責把任務分發給工人。

到直接,這篇博文基本就結束了,因爲兩次更新的時間間隔比較長,最初的思路都記不清了。固然,你確定有一個重要的疑問,那就是若是任務由於系統重啓或者其它緣由崩潰了怎麼重啓呢?對於linux 系統,supervisor能夠託管這兩條命令,若是任務沒有跑起來,它能夠本身重啓啓動任務,這樣,就能保證服務器端的定時任務不會由於一些緣由崩潰掉。

7.推薦文章

1.更深刻的Celery配置:(http://www.cnblogs.com/ajianbeyourself/p/4950758.html)

相關文章
相關標籤/搜索