文件
簡介
Celery 是一個“自帶電池”的的任務佇列。它易於使用,所以你可以無視其所解決問題的複雜程度而輕鬆入門。它遵照最佳實踐設計,所以你的產品可以擴充套件,或與其他語言整合,並且它自帶了在生產環境中執行這樣一個系統所需的工具和支援。
Celery 的最基礎部分。包括:
-
選擇和安裝訊息傳輸方式(中間人)—-broker,如RabbitMQ,redis等。
- RabbitMQ的安裝:sudo apt-get install rabbitmq-server
- 本文使用redis
- 官方推薦RabbitMQ
- 當然部分nosql也可以
- 安裝 Celery 並建立第一個任務
- 執行職程並呼叫任務。
- 追蹤任務在不同狀態間的遷移,並檢視返回值。
安裝
pip install celery
簡單使用
定義任務
tasks.py
from celery import Celery
#第一個引數是你的celery名稱
#backen 用於儲存結果
#broker 用於儲存訊息佇列
app = Celery(`tasks`,backend=`redis://:password@host:port/db`, broker=`redis://:password@host:port/db`)
@app.task
def add(x, y):
return x + y
Celery 的第一個引數是當前模組的名稱,這個引數是必須的,這樣的話名稱可以自動生成。第二個引數是中間人關鍵字引數,指定你所使用的訊息中間人的 URL,此處使用了 RabbitMQ,也是預設的選項。更多可選的中間人見上面的 選擇中間人 一節。例如,對於 RabbitMQ 你可以寫 amqp://localhost ,而對於 Redis 你可以寫 redis://localhost .
你定義了一個單一任務,稱為 add ,返回兩個數字的和。
啟動celery服務
步驟:
- 啟動任務工作者worker
- 講任務放入celery佇列
- worker讀取佇列,並執行任務
啟動一個工作者,建立一個任務佇列
// -A 指定celery名稱,loglevel制定log級別,只有大於或等於該級別才會輸出到日誌檔案
celery -A tasks worker --loglevel=info
如果你沒有安裝redis庫,請先pip install redis
使用celery
現在我們已經有一個celery佇列了,我門只需要將工作所需的引數放入佇列即可
from tasks import add
#呼叫任務會返回一個 AsyncResult 例項,可用於檢查任務的狀態,等待任務完成或獲取返回值(如果任務失敗,則為異常和回溯)。
#但這個功能預設是不開啟的,你需要設定一個 Celery 的結果後端(即backen,我們在tasks.py中已經設定了,backen就是用來儲存我們的計算結果)
result=add.delay(4, 4)
#如果任務已經完成
if(result.ready()):
#獲取任務執行結果
print(result.get(timeout=1))
常用介面
- tasks.add(4,6) —> 本地執行
- tasks.add.delay(3,4) –> worker執行
- t=tasks.add.delay(3,4) –> t.get() 獲取結果,或卡住,阻塞
- t.ready()—> False:未執行完,True:已執行完
- t.get(propagate=False) 丟擲簡單異常,但程式不會停止
- t.traceback 追蹤完整異常
使用配置
- 使用配置來執行,對於正式專案來說可維護性更好。配置可以使用app.config.XXXXX_XXX=`XXX`的形式如app.conf.CELERY_TASK_SERIALIZER = `json`來進行配置
- 配置資料
配置檔案
config.py
#broker
BROKER_URL = `redis://:password@host:port/db`
#backen
CELERY_RESULT_BACKEND = `redis://:password@host:port/db`
#匯入任務,如tasks.py
CELERY_IMPORTS = (`tasks`, )
#列化任務載荷的預設的序列化方式
CELERY_TASK_SERIALIZER = `json`
#結果序列化方式
CELERY_RESULT_SERIALIZER = `json`
CELERY_ACCEPT_CONTENT=[`json`]
#時間地區與形式
CELERY_TIMEZONE = `Europe/Oslo`
#時間是否使用utc形式
CELERY_ENABLE_UTC = True
#設定任務的優先順序或任務每分鐘最多執行次數
CELERY_ROUTES = {
# 如果設定了低優先順序,則可能很久都沒結果
#`tasks.add`: `low-priority`,
#`tasks.add`: {`rate_limit`: `10/m`},
#`tasks.add`: {`rate_limit`: `10/s`},
#`*`: {`rate_limit`: `10/s`}
}
#borker池,預設是10
BROKER_POOL_LIMIT = 10
#任務過期時間,單位為s,預設為一天
CELERY_TASK_RESULT_EXPIRES = 3600
#backen快取結果的數目,預設5000
CELERY_MAX_CACHED_RESULTS = 10000
開啟服務
celery.py
from celery import Celery
#指定名稱
app = Celery(`mycelery`)
#載入配置模組
app.config_from_object(`config`)
if __name__==`__main__`:
app.start()
任務定義
tasks.py
from .celery import app
@app.task
def add(a, b):
return a + b
啟動
// -l 是 --loglevel的簡寫
celery -A mycelery worker -l info
執行/呼叫服務
from tasks import add
#呼叫任務會返回一個 AsyncResult 例項,可用於檢查任務的狀態,等待任務完成或獲取返回值(如果任務失敗,則為異常和回溯)。
#但這個功能預設是不開啟的,你需要設定一個 Celery 的結果後端(即backen,我們在tasks.py中已經設定了,backen就是用來儲存我們的計算結果)
result=add.delay(4, 4)
#如果任務已經完成
if(result.ready()):
#獲取任務執行結果
print(result.get(timeout = 1))
分散式
-
啟動多個celery worker,這樣即使一個worker掛掉了其他worker也能繼續提供服務
- 方法一
// 啟動三個worker:w1,w2,w3 celery multi start w1 -A project -l info celery multi start w2 -A project -l info celery multi start w3 -A project -l info // 立即停止w1,w2,即便現在有正在處理的任務 celery multi stop w1 w2 // 重啟w1 celery multi restart w1 -A project -l info // celery multi stopwait w1 w2 w3 # 待任務執行完,停止
- 方法二
// 啟動多個worker,但是不指定worker名字 // 你可以在同一臺機器上執行多個worker,但要為每個worker指定一個節點名字,使用--hostname或-n選項 // concurrency指定處理程式數,預設與cpu數量相同,因此一般無需指定 $ celery -A proj worker --loglevel=INFO --concurrency=10 -n worker1@%h $ celery -A proj worker --loglevel=INFO --concurrency=10 -n worker2@%h $ celery -A proj worker --loglevel=INFO --concurrency=10 -n worker3@%h
錯誤處理
celery可以指定在發生錯誤的情況下進行自定義的處理
config.py
def my_on_failure(self, exc, task_id, args, kwargs, einfo):
print(`Oh no! Task failed: {0!r}`.format(exc))
// 對所有型別的任務,當發生執行失敗的時候所執行的操作
CELERY_ANNOTATIONS = {`*`: {`on_failure`: my_on_failure}}