非同步任務神器 Celery 簡明筆記

人世間發表於2016-01-07

非同步任務

非同步任務是web開發中一個很常見的方法。對於一些耗時耗資源的操作,往往從主應用中隔離,通過非同步的方式執行。簡而言之,做一個註冊的功能,在使用者使用郵箱註冊成功之後,需要給該郵箱傳送一封啟用郵件。如果直接放在應用中,則呼叫發郵件的過程會遇到網路IO的阻塞,比好優雅的方式則是使用非同步任務,應用在業務邏輯中觸發一個非同步任務。

實現非同步任務的工具有很多,其原理都是使用一個任務佇列,比如使用redis生產消費模型或者釋出訂閱模式實現一個簡單的訊息佇列

除了redis,還可以使用另外一個神器—Celery。Celery是一個非同步任務的排程工具。它是Python寫的庫,但是它實現的通訊協議也可以使用ruby,php,javascript等呼叫。非同步任務除了訊息佇列的後臺執行的方式,還是一種則是跟進時間的計劃任務。下面將會介紹如何使用celery實現這兩種需求。

Celry broker 和 backend

最早學習celery的時候,冒出了一個rabbitmq,又冒出一個redis。當時一頭霧水。實際上這正是celery的設計奧妙。簡單來說,rabbitmq是一個採用Erlang寫的強大的訊息佇列工具。在celery中可以扮演broker的角色。那麼什麼是broker?

broker是一個訊息傳輸的中介軟體,可以理解為一個郵箱。每當應用程式呼叫celery的非同步任務的時候,會向broker傳遞訊息,而後celery的worker將會取到訊息,進行對於的程式執行。好吧,這個郵箱可以看成是一個訊息佇列。那麼什麼又是backend,通常程式傳送的訊息,發完就完了,可能都不知道對方時候接受了。為此,celery實現了一個backend,用於儲存這些訊息以及celery執行的一些訊息和結果。對於 brokers,官方推薦是rabbitmq和redis,至於backend,就是資料庫啦。為了簡單起見,我們都用redis。

Getting Starting

使用celery包含三個方面,其一是定義任務函式,其二是執行celery服務,最後是客戶應用程式的呼叫。

建立一個檔案 tasks.py

輸入下列程式碼:

上述程式碼匯入了celery,然後建立了celery例項app,實力話的過程中,指定了任務名tasks(和檔名一致),傳入了broker和backend。然後建立了一個任務函式add

下面就啟動celery服務

在當前命令列終端執行:

此時會看見一對輸出。包括註冊的任務啦。

下面客戶端程式如何呼叫呢?開啟一個命令列,進入Python環境

在celery命令列可以看見celery執行的日誌:

開啟 backend的redis,也可以看見celery執行的資訊。

現在時在python環境中呼叫的add函式,實際上通常在應用程式中呼叫這個方法。需要注意,如果把返回值賦值給一個變數,那麼原來的應用程式也會被阻塞,需要等待非同步任務返回的結果。因此,實際使用中,不需要把結果賦值。

計劃任務

上述的使用是簡單的配置,下面介紹一個更健壯的方式來使用celery。首先建立一個python包,celery服務,姑且命名為proj。目錄檔案如下:

首先是 celery.py

這一次建立 app,並沒有直接指定 broker 和 backend。而是在配置檔案中。

config.py

剩下的就是tasks.py

使用方法也很簡單,在proj的同一級目錄執行celery:

現在使用任務也很簡單,直接在客戶端程式碼呼叫 proj.tasks 裡的函式即可。

Scheduler

一種常見的需求是每隔一段時間執行一個任務。配置如下

config.py

注意配置檔案需要指定時區。這段程式碼表示每隔30秒執行 add 函式。

一旦使用了 scheduler, 啟動 celery需要加上-B 引數

crontab

計劃任務當然也可以用crontab實現,celery也有crontab模式。修改 config.py

總而言之,scheduler的切分度更細,可以精確到秒。crontab模式就不用說了。當然celery還有更高階的用法,比如多個機器使用,啟用多個worker併發處理等。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

非同步任務神器 Celery 簡明筆記 非同步任務神器 Celery 簡明筆記

相關文章