日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Celery使用過程中遇到的一些問題

本文轉(zhuǎn)載自微信公眾號「新鈦云服」,作者黃平安 。轉(zhuǎn)載本文請聯(lián)系新鈦云服公眾號。

做項(xiàng)目時(shí),其中用了Celery這種工具。前段時(shí)間,遇到過一些問題,解決后沒有進(jìn)行總結(jié),今天就抽個(gè)空把它記錄下來。

用過Celery的程序員,都知道它是一種異步執(zhí)行程序的工具。里面有Worker、Task等概念,這里我就不贅述了。

1、功能需求

在使用Celery的過程中,我需要知道Task的狀態(tài)。Task就是異步任務(wù),用戶沒執(zhí)行一次異步任務(wù),就會(huì)新創(chuàng)建一個(gè)Task,代表此異步任務(wù)。

該Task對象中,包含著許多信息,其中也包括狀態(tài)。我的項(xiàng)目中,需要根據(jù)Task的狀態(tài)來判斷,這次異步任務(wù)是否還在執(zhí)行中。

2、 出現(xiàn)問題

既然,我需要Task的狀態(tài),那我就需要查看Task的狀態(tài)怎么獲取啊!我查看了一下Celery的源碼!發(fā)現(xiàn)在Celery的AsyncResult對象中,有個(gè)state字段。如下圖所示:

根據(jù),該源碼中的注釋說明,該字段有好幾個(gè)值。分別是:PENDING、STARTED、RETRY、FAILURE、SUCCESS。

然后,我就趕緊寫個(gè)demo驗(yàn)證一下,看看這個(gè)state字段是不是我想要的。demo如下:

我執(zhí)行項(xiàng)目中的Celery異步任務(wù),根據(jù)我之前查出來的task id。執(zhí)行demo查詢該Task的狀態(tài)。

這時(shí)候,問題就出來了,根據(jù)demo返回的Task狀態(tài)為PENDING。表示Task還在等待中,尚未執(zhí)行。

這就不對了,此時(shí)的狀態(tài)應(yīng)該是STARTED,因?yàn)槲业腡ask已經(jīng)執(zhí)行好一段時(shí)間了,它返回的結(jié)果不準(zhǔn)確。

3、 解決問題

難道我用的字段不正確,然后我就谷歌搜索。發(fā)現(xiàn)Celery官網(wǎng)和網(wǎng)上的大多數(shù)反饋也是表示Task的狀態(tài)字段就是state。

那我為什么測出的結(jié)果和理論的不同呢?然后,我詳細(xì)查看Celery的配置,發(fā)現(xiàn)了一個(gè)參數(shù):CELERY_TRACK_STARTED。

該參數(shù)默認(rèn)是關(guān)閉的,表示只要Celery開始執(zhí)行Task就會(huì)追蹤該Task。所以,開啟該參數(shù)后,Task的狀態(tài)是時(shí)刻記在BACKEND中的。

好,我在Celery的配置文件處,加了該參數(shù)。

然后再執(zhí)行Celery的異步任務(wù),得到的結(jié)果是我想要的。

4、 引申思考以及問題

我的問題是解決了,但是這引起了我對Celery的一些興趣。

當(dāng)時(shí),我就考慮到,如果我把正在運(yùn)行中的Task任務(wù),直接kill掉。那么此時(shí)我再去看Task的狀態(tài),它會(huì)是啥呢?

STARTED,正在執(zhí)行中的狀態(tài)。

而此時(shí),Task已經(jīng)關(guān)掉,它不應(yīng)該是這種狀態(tài)。為此,我猜測這應(yīng)該是,Task意外結(jié)束,沒有改變Task的狀態(tài)導(dǎo)致的。

但是這樣就不太好了,因?yàn)橹灰浅绦?,那它就一定有意外退出的可能。假設(shè),我的項(xiàng)目需要查看Task的狀態(tài),當(dāng)Task被意外kill掉時(shí),項(xiàng)目中查看Task的狀態(tài)就不準(zhǔn)確了。

5、 引申問題解決思路一

當(dāng)時(shí)我想:既然Task被kill掉之后,還能顯示運(yùn)行中,說明此Task的狀態(tài)一定是保存在某個(gè)地方,我把該Task的數(shù)據(jù)清空了不就完了。

而Celery的數(shù)據(jù)存儲(chǔ),只有可能存在三個(gè)地方:使用RabbitMQ的消息代理(BROKER),使用Redis的任務(wù)結(jié)果保存處(BACKEND),以及文件保存(當(dāng)然這點(diǎn)基本上沒可能,Celery沒這樣用過,我主要是死馬當(dāng)活馬醫(yī))。

這三個(gè)地方,其實(shí)只有Redis可能存放Task的狀態(tài),按照Celery的機(jī)制,也只有它最有可能存放。

但是呢?為了弄清Celery的存儲(chǔ)機(jī)制,我想試試Celery會(huì)把數(shù)據(jù)存到RabbitMQ中嗎?然后,我執(zhí)行了,以下命令,清空RabbitMQ隊(duì)列。

此時(shí),RabbitMQ隊(duì)列的數(shù)據(jù)已經(jīng)為空。然后我查看Task的狀態(tài),依然還為STARTED。說明不是它存儲(chǔ)Task的狀態(tài)。

然后,我進(jìn)入redis中。使用keys *命令,發(fā)現(xiàn)許多帶有celery-task-meta前綴的記錄。

后經(jīng)查明,這些記錄的后綴就是Celery中Task的id。

我根據(jù)我的Task的id,查出如下內(nèi)容:

我們能清晰的看出,內(nèi)容中Task的狀態(tài)為STARTED。這說明的確是存放在Redis中的。然后,我把這條記錄刪除,再執(zhí)行demo,Task的狀態(tài)不再是STARTED,項(xiàng)目中顯示的狀態(tài)就正確了。

但是,這又引出了一個(gè)問題,怎么刪除這條記錄,或者什么時(shí)候刪除這條記錄。當(dāng)然,我們刪除很容易,編程語言的redis模塊或者Celery自己提供的代碼都能刪除。Celery中根據(jù)task id刪除backend中的數(shù)據(jù)。

那么,什么時(shí)候刪除這條記錄呢?Celery默認(rèn)的是保留此數(shù)據(jù)24小時(shí)。我左思右想,還是不刪這條記錄了。換種思路解決這個(gè)問題吧!

6、 引申問題解決思路二

要知道,Celery的Task是運(yùn)行在Worker上的。只要判斷此時(shí)的Worker程序是否還正常運(yùn)行,不就可以判斷Task的狀態(tài)是否還在運(yùn)行中了嗎?

說干就干,我們通過ps命令,可以查看Celery運(yùn)行的程序。

然后,我們執(zhí)行task時(shí),把它本身運(yùn)行的程序進(jìn)程pid記錄下來,發(fā)現(xiàn)正好就是Worker的進(jìn)程pid。

這樣就簡單了,我們只需要結(jié)合Celery提供查看Task狀態(tài)的接口,以及Python提供的Psutil查看進(jìn)程的模塊。就能最終判斷Task是不是真在運(yùn)行中。只有Task的狀態(tài)為STARTED,并且Task所在的Worker進(jìn)程在運(yùn)行中,Task才是真正在運(yùn)行狀態(tài)。

Psutil查看進(jìn)程是否運(yùn)行代碼如下:

7、 總結(jié)

今天只是把我前段時(shí)間遇到的問題以及解決思路記錄下來,也沒寫Celery的內(nèi)部機(jī)制等等,這些東西網(wǎng)上一大把,我也不是很有寫它們的必要。

做過幾年的程序員,感觸最多的就是解決問題的思路。一旦遇到某個(gè)問題了,一種思路解決不了,可以換種思路解決,另一種思路可能也不一定能完美解決,但可以加深對問題的理解。而怎么想到另一種思路,就需要平時(shí)的多積累和提高自己的認(rèn)知范圍了,這還是比較難的。


本文標(biāo)題:Celery使用過程中遇到的一些問題
鏈接URL:http://m.5511xx.com/article/dhgioep.html