Celery在Django中的使用


前段時間用Django開發相關文件下載功能中,碰到一些請求執行的任務時間較長(幾分鍾),前端表現為一直等待后端發來的響應而卡住不動,為了使用戶在前端有個好的體驗,因此決定采用異步任務的方式在后台執行這些任務。在同事的指引下接觸了Celery這個異步任務隊列框架,網上大部分也只是粗粗介紹了大概的流程,在實踐過程中還是遇到了不少坑,希望記錄下來幫助有需要的朋友。(請結合前一篇關於Celery的介紹,你會更加清楚在Django中的使用)

一、Django中的異步請求

Django從一個http請求發起,到獲得響應返回html頁面的流程大致如下:http請求發起 -- http handling(request解析) -- url mapping(url正則匹配找到對應的View) -- 在View中進行邏輯的處理、數據計算(包括調用Model類進行數據庫的增刪改查)--將數據推送到template,返回對應的template/response。

圖1. Django架構總覽

同步請求:所有邏輯處理、數據計算任務在View中處理完畢后返回response。在View處理任務時用戶處於等待狀態,直到頁面返回結果。

異步請求:View中先返回response,再在后台處理任務。用戶無需等待,可以繼續瀏覽網站。當任務處理完成時,我們可以再告知用戶。

二、關於Celery

  Celery是基於Python開發的一個分布式任務隊列框架,支持使用任務隊列的方式在分布的機器/進程/線程上執行任務調度。

圖2. Celery架構

圖2展示的是Celery的架構,它采用典型的生產生-消費者模式,主要由三部分組成:broker(消息隊列)、workers(消費者:處理任務)、backend(存儲結果)。實際應用中,用戶從Web前端發起一個請求,我們只需要將請求所要處理的任務丟入任務隊列broker中,由空閑的worker去處理任務即可,處理的結果會暫存在后台數據庫backend中。我們可以在一台機器或多台機器上同時起多個worker進程來實現分布式地並行處理任務。

三、Django中Celery的實現

在實際使用過程中,發現在Celery在Django里的實現與其在一般.py文件中的實現還是有很大差別,Django有其特定的使用Celery的方式。這里着重介紹Celery在Django中的實現方法,簡單介紹與其在一般.py文件中實現方式的差別。

  1. 建立消息隊列

  首先,我們必須擁有一個broker消息隊列用於發送和接收消息。Celery官網給出了多個broker的備選方案:RabbitMQ、Redis、Database(不推薦)以及其他的消息中間件。官網的強力推薦RabbitMQ,作為運維我使用Redis比較多,就使用Redis作為消息中間人。在Linux上安裝的方式大致如下:

從官網下載src或者從其他機器上copy,如果是之前線上使用的redis,配置文件里可能配置了客戶端驗證相關的選項,再啟動celery-worker的時候會報驗證失敗等信息,如requirepass等注釋:

  2. 安裝django-celery

  當前部署環境為:Centos7.2(64bit),python版本從2.7.5升級到了2.7.13,Django使用的是1.11,使用如下命令進行安裝相關組件:

pip install celery
pip install django-celery

  3. 配置settings.py

  在Django工程的settings.py(/export/App/mypro/mypro)文件中加入如下配置代碼:

import djcelery
djcelery.setup_loader()
BROKER_URL= 'redis://127.0.0.1:6379'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0'

  其中,當djcelery.setup_loader()運行時,Celery便會去查看INSTALLD_APPS下包含的所有app目錄中的tasks.py文件,找到標記為@task的方法,將它們注冊為celery task。BROKER_URL和CELERY_RESULT_BACKEND分別指代你的Broker的代理地址以及Backend(result store)數據存儲地址。在Django中如果沒有設置backend,會使用其默認的后台數據庫用來存儲數據。注意,此處backend的設置是通過關鍵字CELERY_RESULT_BACKEND來配置,與一般的.py文件中實現celery的backend設置方式有所不同。一般的.py中是直接通過設置backend關鍵字來配置,如下所示:

app = Celery('tasks', backend=''redis://127.0.0.1:6379'', broker='redis://127.0.0.1:6379/0')

  然后,在INSTALLED_APPS中加入djcelery:

INSTALLED_APPS = (
    ……   
    'download',
    'djcelery'
    ……   
)  

  4. 在要異步處理的app根目錄下(比如download),建立tasks.py,比如:

圖3.模塊導入及裝飾器

在tasks.py中我們就可以編碼實現我們需要執行的任務邏輯,在開始處import task,然后在要執行的任務方法開頭用上裝飾器@task。需要注意的是,與一般的.py中實現celery不同,tasks.py必須建在各app的根目錄下,且不能隨意命名。

  5. 生產任務

  在需要執行該任務的View中,通過yum_expect.delay(ip)的方式來創建任務,並送入消息隊列。比如:

  6. 啟動worker的命令

#先啟動服務器
python manage.py runserver
#再啟動worker 
python manage.py celery worker -c 4 --loglevel=info

四、補充

Django下要查看其他celery的命令,包括參數配置、啟動多worker進程的方式都可以通過python manage.py celery --help來查看:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM