任務(wù)調(diào)度delay&apply_async
delay與apply_async都是用來做任務(wù)調(diào)度凛驮,但如果查看delay的源碼會發(fā)現(xiàn)最終還是調(diào)用了apply_async厚者,簡單來說delay就是apply_async的快捷方式,而apply_async則有很多參數(shù)來控制任務(wù)調(diào)度撬即。
apply_async支持常用參數(shù):
- eta:指定任務(wù)執(zhí)行時間宰缤,類型為datetime時間類型颂翼;
- countdown:倒計時,單位秒,浮點類型慨灭;
- expires:任務(wù)過期時間朦乏,如果任務(wù)在超過過期時間還未執(zhí)行則回收任務(wù),浮點類型獲取datetime類型缘挑;
- retry:任務(wù)執(zhí)行失敗時候是否嘗試集歇,布爾類型。语淘;
- serializer:序列化方案,支持pickle际歼、json惶翻、yaml、msgpack鹅心;
- priority:任務(wù)優(yōu)先級吕粗,有0~9優(yōu)先級可設(shè)置,int類型旭愧;
- retry_policy:任務(wù)重試機制颅筋,其中包含幾個重試參數(shù)宙暇,類型是dict如下:
max_retries:最大重試次數(shù)
interval_start:重試等待時間
interval_step:每次重試疊加時長,假設(shè)第一重試等待1s议泵,第二次等待1+n秒
interval_max:最大等待時間
Celery設(shè)置參數(shù)說明
- CELERY_DEFAULT_QUEUE 默認隊列
- CELERY_RESULT_BACKEND 存儲地址
- CELERY_TASK_SERIALIZER 任務(wù)序列化方式
- CELERY_RESULT_SERIALIZER 任務(wù)結(jié)果序列化方式
- CELERY_TASK_RESULT_EXPIRES 任務(wù)過期時間
- CELERYD_CONCURRENCY 任務(wù)并發(fā)數(shù)
- CELERYBEAT_SCHEDULE 任務(wù)調(diào)度
- CELERY_QUEUE 自定義任務(wù)隊列
CELERY_QUEUE = (
Queue('default',exchange=Exchange('default'), routing_key="default.#"), # 路由鍵 以 "default." 開頭的消息都進入 default 隊列.
Queue('task1_app',exchange=Exchange('task1'), routing_key="task1.#") # 路由鍵 以 "web." 開頭的消息都進入 task1隊列.
)
- CELERY_ROUTES 自定義任務(wù)路由
CELERY_ROUTES = {
'celery_app.app_task1.auto_crawl':{'queue':'task1','routing_key':'task1'},
'celery_app.app_task1.auto_download':{'queue':'task1','routing_key':'task1'},
'celery_app.app_task1.timelycrawl': {'queue': 'task2', 'routing_key': 'task2'},
'celery_app.app_task1.timelydownload': {'queue': 'task2', 'routing_key': 'task2'}
}
- CELERY_ACCEPT_CONTENT 指定過任務(wù)接受內(nèi)容的格式
CELERYBEAT_SCHEDULE = {
'add': {
'task': 'proj.tasks.add', #任務(wù)的路勁
'schedule': timedelta(seconds=10), #定時啟動時間,也可以用crontab
'args': (16, 16) #任務(wù)參數(shù)
}
Celery的存儲問題
在使用定時任務(wù)的時候我發(fā)現(xiàn)了一個問題占贫,就是當(dāng)你有兩個定時任務(wù)(task1,task2)時先口,兩個的定時時間相同比如都是一分鐘型奥,
然后task1的執(zhí)行時間較長要2分鐘,而task2的執(zhí)行時間只要兩秒碉京,理想狀態(tài)下是task1在執(zhí)行但因為時間較長厢汹,會掛起,然后在掛起的時間里定時的去執(zhí)行task2谐宙。但實際情況下烫葬,當(dāng)進行task1的時候,在task1未執(zhí)行完的時候凡蜻,task2并不執(zhí)行搭综,然后當(dāng)task1執(zhí)行完時,task2會立馬執(zhí)行好幾次咽瓷。
下圖就是设凹,celery的流程:
從該圖可以看出,造成該原因的是因為只有一個Woker茅姜,在從任務(wù)隊列里面拿出一個任務(wù)時闪朱,在沒執(zhí)行完當(dāng)前任務(wù)的時候是不會在往任務(wù)隊列里面拿去任務(wù),但task2在每兩秒內(nèi)會往該任務(wù)隊列里面放入任務(wù),所以根據(jù)隊列先進先出的原則钻洒,在task1執(zhí)行完時奋姿,會立馬執(zhí)行好幾次的task2
解決方案:
解決的方法就是,增加并發(fā)數(shù)素标,也就是在設(shè)置里面添加CELERYD_CONCURRENCY參數(shù)称诗,每個woker在閑空的時候就會自動去任務(wù)隊列里面拿任務(wù)就不會造成任務(wù)阻塞。
所以定時任務(wù)最好不要放多個互相之間有依賴關(guān)系的任務(wù)