【celery】異步組件

1. Celery概念
Celery是處理大量消息的分布式系統(tǒng),專注于實(shí)時(shí)處理的異步任務(wù)隊(duì)列,同時(shí)也支持任務(wù)調(diào)度。
Celery架構(gòu)由三部分組成:
消息中間件
Celery本身不提供消息服務(wù),但是可以和第三方消息中間件集成,例如RabbitMQ、Redis等,
任務(wù)執(zhí)行單元
任務(wù)執(zhí)行單元并發(fā)地運(yùn)行在分布式的系統(tǒng)節(jié)點(diǎn)中。
任務(wù)執(zhí)行結(jié)果存儲(chǔ)
用來存儲(chǔ)Worker執(zhí)行的任務(wù)的結(jié)果,Celery支持以不同方式存儲(chǔ)任務(wù)的結(jié)果,包括AMQP、redis等。
這三部分的關(guān)系如下圖所示:

Celery使用場(chǎng)景:
異步任務(wù)
將耗時(shí)操作任務(wù)提交給Celery去異步執(zhí)行,比如發(fā)送短信/郵件、消息推送、音視頻處理等等。
定時(shí)任務(wù)
定時(shí)執(zhí)行某件事情,比如每天數(shù)據(jù)統(tǒng)計(jì)。
Celery安裝
2. Celery使用
環(huán)境信息:
平臺(tái): win10, redis 6.0.16是部署在ubuntu虛擬機(jī)上的
python 3.8
celery 5.2.7
django 4.1.4
2.1 單目錄結(jié)構(gòu)
2.1.1 消費(fèi)者
創(chuàng)建celery任務(wù)
執(zhí)行celery任務(wù):
windows環(huán)境:
-A 表示應(yīng)用 ,20_1_demo是應(yīng)用文件名稱;
worker表示啟動(dòng)任務(wù)實(shí)例;
-l info表示輸出的日志級(jí)別為info
-P 指定使用eventlet(綠色線程,待了解)
-c 并發(fā)數(shù)
linux環(huán)境:
注: 在windows上使用linux命令啟動(dòng)celery監(jiān)聽后,發(fā)現(xiàn)生產(chǎn)者發(fā)送過來的消息,celery任務(wù)一直運(yùn)行不起來,需要指定-P eventlet才能正常運(yùn)行。
這個(gè)命令做的事情:
連接消息中間件,創(chuàng)建消息隊(duì)列,監(jiān)聽消息隊(duì)列
創(chuàng)建多個(gè)worker,監(jiān)聽任務(wù)
這個(gè)時(shí)候消費(fèi)者任務(wù)(send_email、send_msg)還沒有運(yùn)行,只是掃描監(jiān)聽到了,運(yùn)行結(jié)果:

下圖是redis2號(hào)庫里生成的數(shù)據(jù):

2.1.2 生產(chǎn)者
向消息隊(duì)列中添加消息,消息隊(duì)列中保存的內(nèi)容是:函數(shù)名和參數(shù)
運(yùn)行之后將兩個(gè)任務(wù)的id輸出,這個(gè)時(shí)候并不能保證任務(wù)運(yùn)行結(jié)束了,生產(chǎn)者只需要把消息發(fā)送到消息隊(duì)列里即可,任務(wù)運(yùn)行成功或失敗需要查詢才能知道。

查詢?nèi)蝿?wù)是否運(yùn)行成功:
運(yùn)行結(jié)果:

由第1章的Celry原理圖,可以知道,任務(wù)運(yùn)行成功之后會(huì)將結(jié)果保存到數(shù)據(jù)庫里,這兒打印出來的ok是從數(shù)據(jù)庫讀取出來的,查看下redis1號(hào)庫中的內(nèi)容,發(fā)現(xiàn)程序輸出結(jié)果和庫里的內(nèi)容保持一致,輸出結(jié)果還保存了其他信息,比如:任務(wù)狀態(tài)、任務(wù)完成時(shí)間、任務(wù)id等。

2.2 多目錄結(jié)構(gòu)
多目錄結(jié)構(gòu)和單目錄結(jié)構(gòu)的區(qū)別就是:celery任務(wù)放在了不同的文件里。
下面是例子:

啟動(dòng)方式:
需要進(jìn)入到目錄celery_tasks上一層目錄執(zhí)行,-A指定的應(yīng)用為目錄名稱celery_tasks
消費(fèi)者啟動(dòng)之后,生產(chǎn)者和2.1.2章內(nèi)容沒什么區(qū)別。
生產(chǎn)者將消息存入到消息隊(duì)列后,任務(wù)執(zhí)行完畢,從終端輸出可以看出celery任務(wù)輸出內(nèi)容和返回結(jié)果:

3. Celery簡單結(jié)構(gòu)下的定時(shí)任務(wù)
3.1 方式一:自定義幾點(diǎn)幾分運(yùn)行
Celery消費(fèi)者任務(wù)要提前啟動(dòng),等待生產(chǎn)者推送消息。生產(chǎn)者定時(shí)推送消息使用的是函數(shù)apply_async。
函數(shù)apply_async包含如下參數(shù):
args: celery任務(wù)接受的參數(shù),以列表形式展示,例如下方代碼中send_email任務(wù)需要接收一個(gè)參數(shù)name。
eta: 定時(shí)時(shí)間,下方代碼中指定時(shí)間,再轉(zhuǎn)換為時(shí)間戳,再轉(zhuǎn)換為國標(biāo)時(shí)間,傳遞給參數(shù)eta,Celery任務(wù)會(huì)在指定時(shí)間調(diào)用。
代碼:

3.2 方式二:指定多長時(shí)間后運(yùn)行任務(wù)
使用datetime.timedelta()做時(shí)間間隔定時(shí)。

4. Celery多目錄結(jié)構(gòu)下的定時(shí)任務(wù)
4.1 定時(shí)任務(wù)配置
第2章中多目錄結(jié)構(gòu)配置文件celery.py中配置定時(shí)任務(wù):
注意:beat_schedule千萬不要寫為beat_scheduler
調(diào)度器beat_schedule每個(gè)子元素都是一個(gè)定時(shí)任務(wù),子元素的key是定時(shí)任務(wù)的名稱,可以隨意寫;子元素的內(nèi)容里的key是固定的,不可以改。
定時(shí)方式設(shè)置:
timedelta(seconds=10): 每隔10秒鐘調(diào)用一次
crontabl(minute="*/2"): 每隔2分鐘調(diào)用一次。
定時(shí)任務(wù)配置代碼參考:
4.2 work啟動(dòng)
work就是消費(fèi)者,把Celery任務(wù)準(zhǔn)備好之后,等待生產(chǎn)者往消息隊(duì)列里插入數(shù)據(jù)后,讀取消息進(jìn)行消費(fèi)(運(yùn)行Celery任務(wù))。
如下圖所示:celery beat啟動(dòng)之后,每隔2分鐘調(diào)用一次任務(wù)。

4.3 celery beat啟動(dòng)定時(shí)任務(wù)
定時(shí)任務(wù)是生產(chǎn)者的角色,按配置的時(shí)間將任務(wù)消息(Celery任務(wù)函數(shù)名稱、參數(shù)、任務(wù)id等信息組成的消息)插入消息隊(duì)列。

5. Django中使用Celery完成異步和定時(shí)任務(wù)
先看下目錄結(jié)構(gòu):
Django項(xiàng)目創(chuàng)建之后,創(chuàng)建celery消費(fèi)者目錄,這里面存放Celery任務(wù)。

5.1 創(chuàng)建celery配置
5.2 創(chuàng)建celery任務(wù)
任務(wù)包名email和sms可以任意修改,但是報(bào)名下的tasks.py不可以修改,celery識(shí)別任務(wù)時(shí)會(huì)根據(jù)tasks.py進(jìn)行任務(wù)掃描。

5.3 創(chuàng)建celery實(shí)例并啟動(dòng)
這一部分是創(chuàng)建Celery實(shí)例應(yīng)用,把celery的配置config.py和任務(wù)加載進(jìn)來。
啟動(dòng)Celery任務(wù)命令:
5.4 Django視圖調(diào)用Celery任務(wù)
此時(shí)的Django視圖相當(dāng)于生產(chǎn)者,當(dāng)訪問到test()視圖時(shí),會(huì)調(diào)起Celery任務(wù)(就是把任務(wù)消息放到消息隊(duì)列里),消費(fèi)者端會(huì)根據(jù)任務(wù)類型(異步任務(wù)/定時(shí)任務(wù))執(zhí)行對(duì)應(yīng)的Celery任務(wù)。
訪問之后,消費(fèi)者端可以成功接收任務(wù)并執(zhí)行:

6. 參考資料
B站視頻: BV1tq4y187k5 (推薦)
Celery官方文檔: https://docs.celeryq.dev/en/stable/index.html (輔助)
練習(xí)代碼上傳至:https://gitee.com/atiaisi/py_learn/tree/master/20_Celery%E5%BC%82%E6%AD%A5%E6%A1%86%E6%9E%B6