celery(一) application
Application
application
- celery在使用之前,必須首先實例化。e.g.
app = Celery()
- app 是線程安全的,即:不同配置、組件和任務的多個app可以共存在同一個進程空間。
任務註冊表(task-registry)
在Celery中發送一個task 消息,這個消息並不包含任何源代碼(函數體)。而是只有你所期望執行的task的名字。每個worker有一個任務註冊表(task-registry),它是task 名稱與 task 源代碼(函數)的映射。每當你定義一個task,這個task就會被註冊到本地的註冊表中
懶加載
Celery創建app實例是延遲的,只有在調用它的時候才會創建。也就是說,Celery()命令並沒有立即創建app實例。
Celery實例化的過程中,做了如下操作:
- 創建了一個邏輯時鐘,用於events
- 創建了一個任務註冊表 task-registry
- 設置它自己為當前的Celery實例(如果
set_as_current
參數被置為disabled,那麽就不會進行該操作) - 調用
app.on_init()
(默認情況下,啥都沒做)
@app.task
裝飾器也是延遲創建task的。task被定義的時候(在一個函數頭上加裝飾器的時候),task並沒有立即創建。在task被使用的時候,或者是app finalized 的時候,task才會創建
finalized 做了如下操作:
- task是在多app之間共享的,拷貝task。(shard參數可以取消共享,使task獨屬於其綁定的app)
- 創建所有的task
- 確保所有的task都綁定到當前的app(只有綁定app,task才能讀取默認的配置)
Main name
task 默認的名稱組成是 model.fun
e.g. tasks.add
。
當model名獲取不到的時候就會以 __main__
作為model名。因此會出現 某task以 __main__.add
為名註冊到 任務註冊表之後,當某個task被引入到其他模塊時,會以源模塊.task
作為任務名,這個時候,就會出現不一致的情況,所以,在Celery實例化的時候一定要指定app的名字。e.g. app=Celery(‘tasks’)
配置Celery
Celery的配置有如下幾種:
- 直接配置app屬性
- 使用配置文件
直接配置app屬性
- 單個配置
app.conf.enable_utc = True
- 多個配置
app.conf.update(enable_utc=True, timezone=‘Asia/Shanghai‘)
使用配置文件
從配置文件加載配置,使用 app.config_from_object()
和 app.config_from_envvar()
方法。
config_from_object
app = Celery()
app.config_from_object(‘celeryconfig.py‘)
# 項目中要有 celeryconfig.py 文件
from xxxx import configmodel
app = Celery()
app.config_from_object(configmodel)
class Config:
enable_utc = True
app = Celery()
app.config_from_object(Config)
config_from_envva
從環境變量加載指定模塊
app.config_from_envvar(‘CELERY_CONFIG_MODEL‘)
Task
所有使用 @task()
裝飾器定義的task,都繼承自基類 Task
。你也可以指定自己的基類 Task
。
- 在裝飾器中指定其他類
@app.task(base=OtherTask)
def function():
...
- 在配置中指定其他類
app = Celery()
app.Task = OtherTask
自定義 Task
所有的自定義 Task
都必須
繼承自 Task
類
class MyTask(Task):
...
最佳實踐是 app 作為參數傳給需要它的地方
class SomeClass:
def __init__(self, app):
self.app = app
...
celery(一) application