1. 程式人生 > >Django中使用django-celery完成非同步任務(1)

Django中使用django-celery完成非同步任務(1)

許多Django應用需要執行非同步任務, 以便不耽誤http request的執行. 我們也可以選擇許多方法來完成非同步任務, 使用Celery是一個比較好的選擇, 因為Celery有著大量的社群支援, 能夠完美的擴充套件, 和Django結合的也很好. Celery不僅能在Django中使用, 還能在其他地方被大量的使用. 因此一旦學會使用Celery, 我們可以很方便的在其他專案中使用它.

Celery介紹

  • Celery的主要用處是執行非同步任務, 可以選擇延期或定時執行功能
  • 適用於以下的場景
  • 第一, 假設使用者正發起一個request, 並等待request完成後返回. 在這一request後面的view功能中, 我們可能需要執行一段花費很長時間的程式任務, 這一時間可能遠遠大於使用者能忍受的範圍. 當這一任務並不需要立刻執行時, 我們便可以使用Celery在後臺執行, 而不影響使用者瀏覽網頁. 當有任務需要訪問遠端伺服器完成時, 我們往往都無法確定需要花費的時間.
  • 第二則是定期執行某些任務. 比如每小時需要檢查一下天氣預報, 然後將資料儲存到資料庫中. 我們可以編寫這一任務, 然後讓Celery每小時執行一次. 這樣我們的web應用便能獲取最新的天氣預報資訊.

我們這裡所講的任務task, 就是一個Python功能(function). 定期執行一個任務可以被認為是延時執行該功能. 我們可以使用Celery延遲5分鐘呼叫function task1, 並傳入引數(1, 2, 3). 或者我們也可以每天午夜執行該function.

我們偏向於將Celery放入專案中, 便於task訪問統一資料庫和Django設定.

當task準備執行時, Celery會將其放入列隊queue中. queue中儲存著可以執行的task的list. 我們可以使用多個queue,

將任務task放入queue就像加入todo list一樣. 為了使task執行, 我們還需要在其他執行緒中執行的苦工worker. worker實時觀察著代執行的task, 並逐一執行這些task. 你可以使用多個worker, 通常他們位於不同伺服器上.

安裝Celery

pip install django-celery

django 中的配置

暫時使用django runserver來啟動celery. 而Celery代理人(broker), 我們使用Django database broker implementation. 現在我們只需要知道Celery需要broker, 使用django自身便可以充當broker. (但在部署時, 我們最好使用更穩定和高效的broker, 例如Redis.)

在settings中配置

import djcelery
    djcelery.setup_loader()
    BROKER_URL = 'django://'
    ...
    INSTALLED_APPS = (
       ...
       'djcelery',
       'kombu.transport.django',
       ...
    )

第一二項是必須的, 第三項則告訴Celery使用Django專案作為broker.

在INSTALLED_APPS中新增的djcelery是必須的. kombu.transport.django則是基於Django的broker

最後建立Celery所需的資料表, 使用makemigrations 和 migrate 命令建立表結構

建立一個task任務

正如前面所說的, 一個task就是一個Pyhton function. 但Celery需要知道這一function是task, 因此我們可以使用celery自帶的裝飾器decorator: @task. 在django app目錄中建立taske.py:

 from celery import task

    @task()
    def add(x, y):
        return x + y

當settings.py中的djcelery.setup_loader()執行時, Celery便會檢視所有INSTALLED_APPS中app目錄中的tasks.py檔案, 找到標記為task的function, 並將它們註冊為celery task.

將function標註為task並不會妨礙他們的正常執行. 你還是可以像平時那樣呼叫它: z = add(1, 2).

開始執行task

讓我們以一個簡單的例子作為開始. 例如我們希望在使用者發出request後非同步執行該task, 馬上返回response, 從而不阻塞該request, 使使用者有一個流暢的訪問過程. 那麼, 我們可以使用.delay, 例如在在views.py的一個view中:

  from myapp.tasks import add
    ...
        add.delay(2, 2)
    ...

Celery會將task加入到queue中, 並馬上返回. 而在一旁待命的worker看到該task後, 便會按照設定執行它, 並將他從queue中移除. 而worker則會執行以下程式碼:

    import myapp.tasks.add

    myapp.tasks.add(2, 2)

關於 import

這裡需要注意的是, 在impprt task時, 需要保持一致. 因為在執行djcelery.setup_loader()時, task是以INSTALLED_APPS中的app名, 加.tasks.function_name註冊的, 如果我們由於python path不同而使用不同的引用方式時(例如在tasks.py中使用from myproject.myapp.tasks import add形式), Celery將無法得知這是同一task, 因此可能會引起奇怪的bug.

測試

  • 啟動worker
    正如之前說到的, 我們需要worker來執行task. 以下是在開發環境中的如何啟動worker:

首先啟動terminal, 如同開發django專案一樣, 啟用virtualenv, 切換到django專案目錄. 然後啟動django自帶web伺服器: python manage.py runserver.

然後啟動worker:

python manage.py celery worker --loglevel=info

此時, worker將會在該terminal中執行, 並顯示輸出結果.

  • 啟動task
  • 開啟新的terminal, 啟用virtualenv, 並切換到django專案目錄:
 $ python manage.py shell
    >>> from myapp.tasks import add
    >>> add.delay(2, 2)

此時, 你可以在worker視窗中看到worker執行該task:

下面我們來看一個例子, 在views.py和tasks.py中:

# views.py
    from myapp.tasks import do_something_with_form_data

    def view(request):
        form = SomeForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data
            # Schedule a task to process the data later
            do_something_with_form_data.delay(data)
        return render_to_response(...)
# tasks.py

    @task
    def do_something_with_form_data(data):
        call_slow_web_service(data['user'], data['text'], ...)

除錯

由於Celery的執行需要啟動多個部件, 我們可能會漏掉一兩個. 所以我們建議:

使用最簡單的設定
使用python debug和logging功能顯示當前的程序

Eager模式

如果在settings.py設定:

    CELERY_ALWAYS_EAGER = True
那麼Celery便以eager模式執行, 則task便不需要加delay執行:

    # 若啟用eager模式, 則以下兩行程式碼相同
    add.delay(2, 2)
    add(2, 2)

檢視queue

因為我們使用了django作為broker, queue儲存在django的資料庫中. 這就意味著我們可以通過django admin檢視該queue:

# admin.py
    from django.contrib import admin
    from kombu.transport.django import models as kombu_models

    admin.site.register(kombu_models.Message)

檢查結果

每次執行非同步task後, Celery都會返回AsyncResult物件作為結果. 你可以將其儲存, 然後在將來檢視該task是否執行成功和返回結果:

# views.py

result = add.delay(2, 2)
...
if result.ready():
    print "Task has run"
    if result.successful():
        print "Result was: %s" % result.result
    else:
        if isinstance(result.result, Exception):
            print "Task failed due to raising an exception"
            raise result.result
        else:
            print "Task failed without raising exception"
 else:
     print "Task has not yet run"

定期任務

還有一種Celery的常用模式便是執行定期任務. 執行定期任務時, Celery會通過celerybeat程序來完成. Celerybeat會保持執行, 一旦到了某一定期任務需要執行時, Celerybeat便將其加入到queue中. 不像worker程序, Celerybeat只有需要一個即可.

啟動Celerybeat:

python manage.py celery beat

使Celery執行定期任務的方式有很多種, 我們先看第一種, 將定期任務儲存在django資料庫中. 即使是在django和celery都執行的狀態, 這一方式也可以讓我們方便的修改定期任務. 我們只需要設定settings.py中的一項便能開啟這一方式:

# settings.py
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'

然後我們便可以通過django admin的/admin/djcelery/periodictask/新增定期任務了.

Name: 這一定期任務的註冊名
Task (registered): 可以選擇所有已經註冊的task之一, 例如前面的add function
Task (custom): task的全名, 例如myapp.tasks.add, 但最好還是用以上項
Enabled: 是否開啟這一定期任務
Interval: 定期任務的間隔時間, 例如每隔5分鐘
Crontab: 如果希望task在某一特定時間執行, 則使用Unix中的Crontab代替interval
Arguments: 用於傳引數到task中

相關推薦

Django通過celery完成非同步任務

開發環境: Django:1.11 專案佈局 安裝 celery: pip install celery 非同步任務模組 celery_tasks; 非同步任務: sms (傳送簡訊); config: celery非同步任務的配置(這裡是用來指名非同步任務儲存的位置)

Django使用django-celery完成非同步任務(1)

許多Django應用需要執行非同步任務, 以便不耽誤http request的執行. 我們也可以選擇許多方法來完成非同步任務, 使用Celery是一個比較好的選擇, 因為Celery有著大量的社群支援, 能夠完美的擴充套件, 和Django結合的也很好. Cel

Django使用Celery實現定時任務(用djcelery)

三方庫 span 托管 沒有 日報 目錄結構 elf beat worker [TOC] 一.引言 Django是python語言下的一個比較熱門的Web框架,越來越多的企業和開發者使用Django實現自己的Web服務器。在Web服務器開發過程中,有時候我們不僅僅是要實現W

Python--Django使用celery實現非同步任務

Django使用celery實現非同步任務 celery使用: 以傳送簡訊為例 在專案目錄下下建立celery_tasks用於儲存celery非同步任務。 在celery_tasks目錄下建立config.py檔案,用於儲存celery的配置資訊 # redi

Django 使用 Celery 實現非同步任務

對於網站來說,給使用者一個較好的體驗是很重要的事情,其中最重要的指標就是網站的瀏覽速度。因此服務端要從各個方面對網站效能進行優化,比如可採用CDN載入一些公共靜態檔案,如js和css;合併css或者js從而減少靜態檔案的請求等等…..還有一種方法是將一些不需要立即返回給使用者,

Python Django Celery 實現非同步任務(二)使用rabbitmq 作為broker

之前在上一篇文章中Python Celery 實現非同步任務是使用Django預設作為borker (訊息分發),因為升級最新的celery後,不再支援Django作為borker ,所以測試平臺更換為

Django配置celery執行非同步任務和定時任務

原生celery,非djcelery模組,所有演示均基於Django2.0 celery是一個基於python開發的簡單、靈活且可靠的分散式任務佇列框架,支援使用任務佇列的方式在分散式的機器/程序/執行緒上執行任務排程。採用典型的生產者-消費者模型,主

Celery 分布式任務隊列快速入門 以及在Django動態添加定時任務

快速入門 change pwa waiting processes 中間件 peid eas 復雜 Celery 分布式任務隊列快速入門 以及在Django中動態添加定時任務 轉自 金角大王 http://www.cnblogs.com/alex3714/articles/

Django使用Celery的配置方法

req sudo targe success apt-get ask ive rate info 這幾天想要在練習的Django項目中使用celery來完成一個定時的功能,但是因為前輩們的教程大都年代久遠我在配置celery的過程中遇到了很多麻煩。因此我在配置完成後寫下這篇

Django使用Celery

模組: Python 3.6.6 PyMySQL==0.8.1 Django==2.1.3 redis==3.0.1 celery==4.1.1 django-celery-beat ==1.1.1 django-celery-results==1.0.1 目錄結構 emgc

flaskcelery介紹及使用celery實現非同步任務

Celery簡介 除Celery是一個非同步任務的排程工具。 Celery 是 Distributed Task Queue,分散式任務佇列,分散式決定了可以有多個 worker 的存在,隊列表示其是非同步操作,即存在一個產生任務提出需求的工頭,和一群等著

使用redis和celery執行非同步任務時報錯AttributeError: 'str' object has no attribute 'iteritems'

程式碼基本配置正常,但是執行Celery -A myproject worker -l info執行的時候了一個AttributeError: ‘str’ object has no attribute 'iteritems’錯誤,找了兩天看到一個部落格裡的文章,錯誤問題和我的問題內容差

在C#使用 CancellationToken 處理非同步任務

在 .NET Core 中使用非同步程式設計已經很普遍了, 你在專案中隨處可見 async 和 await,它簡化了非同步操作,允許開發人員,使用同步的方式編寫非同步程式碼,你會發現在大部分的非同步方法中,都提供了CancellationToken引數,本文主要介紹下 CancellationTokenSou

異步任務利器Celery(二)在django項目使用Celery

ace credit site spam 數據表 del files rtc field Celery 4.0支持django1.8及以上的版本,低於1.8的項目使用Celery 3.1。 一個django項目的組織如下: - proj/ - manage.py

Django項目使用celery做異步任務

led swagger 讀取 celery messages RoCE 個人 none 後臺 異步任務介紹 在寫項目過程中經常會遇到一些耗時的任務, 比如:發送郵件、發送短信等等~。這些操作如果都同步執行耗時長對用戶體驗不友好,在這種情況下就可以把任務放在後臺異步執行 ce

Django搭配Celery進行非同步/定時任務(一)初步搭建

以下需求場景很常見: 1. 使用者點選頁面按鈕,請求後臺進行一系列耗時非常高的操作,頁面沒有響應/一直Loading,使用者體驗非常不好。 2. 某些資料需要預先處理,每天凌晨的時候進行運算,大約半小時到1小時才能完成。 3. 進行外部系統的介面資料呼叫,介面要求在10秒內返回應答報

Django+celery+ RabbitMQ實現非同步任務

一,首先安裝celery pip install django-celery 二,安裝rabbitmq ubuntu環境下執行以下 sudo apt-get install rabbitmq-server 新增使用者,myuser為使用者名稱,mypassword為使用者

django非同步任務celery+rabbitmq+flower視覺化)

文章目錄 安裝rabbitmq 安裝django-celery,flower 配置過程 安裝rabbitmq sudo apt-get install rabbitmq-server 新增使用者,myuser為

Django框架,使用celery實現非同步

作用:在使用框架時,在檢視函式中實現非同步構成: 任務task:一段耗時並與響應結果無關的程式碼,如發簡訊 工人worker:新程序,用於執行任務程式碼 代理人broker:呼叫任務時,將任務新增到佇列中,通知worker執行 佇列queue:用於儲存待執行的任務 呼叫:任務函式.delay(引數) 說明

django-celery定時任務以及非同步任務and伺服器部署並且執行全部過程

Celery 應用Celery之前,我想大家都已經瞭解了,什麼是Celery,Celery可以做什麼,等等一些關於Celery的問題,在這裡我就不一一解釋了。 應用之前,要確保環境中添加了Celery包。 pip install celery pip install dajngo-celery