flask + celery 遇到的那些坑

特么的。。。寫好的東西不見了一半。。。又得重寫。。
星期一開始,有同事和我說要不要把我們的項(xiàng)目加上celery,異步發(fā)送郵件。我想了想這塊我沒碰過,正好學(xué)點(diǎn)新東西。
celery是干什么的,我這里抄點(diǎn)別人的文字

###來源 http://www.ziyoubaba.com/archives/590

flask是一個(gè)阻塞式的框架。這里的“阻塞”是指flask處理請求的時(shí)候,一次只能處理一個(gè),當(dāng)多個(gè)requests過來,flask會(huì)說,大家不要急,一個(gè)一個(gè)來。如果恰好這時(shí)候某個(gè)請求耗費(fèi)了大量的時(shí)間(種種原因),在這段時(shí)間內(nèi),flask說:我忙著呢,后來的排好隊(duì)。然后服務(wù)進(jìn)程被占用著,后來的請求得不到處理。這就叫做被阻塞住了。說得再多不如一只栗子:
def long_time_def():
    for _ in range(10000):
        for j in range(10000):
            i = 1
    return 'hello'

我的老爺機(jī)運(yùn)行這只函數(shù)需要大約8s的時(shí)間,可以很好地用來充當(dāng)“阻塞俠”的角色。如果你的本配置比較好,可以適當(dāng)增大數(shù)字。然后我們這么構(gòu)建一個(gè)flask服務(wù)端:

###  flask_celery.py  ###
app = Flask(__name__)

@app.route("/")
def hello():
    print ("耗時(shí)的請求")
    result=long_time_def()
    return result

@app.route('/t')
def test():
    return 'test!'

if __name__ == "__main__":
    app.run(debug=True)

    


運(yùn)行一下,同時(shí)訪問‘/’與‘/t’你就能明白,當(dāng)‘/’未返回結(jié)果的時(shí)候,‘/t’是沒有響應(yīng)的。

多進(jìn)程的方案只能說可以緩解這種“阻塞”,但無法根治,因?yàn)檫M(jìn)程有限,訪問量不可控,早晚所有進(jìn)程都被阻塞。所以一個(gè)分布式的任務(wù)隊(duì)列框架被搬上臺(tái)面:celery。

celery會(huì)這么說:flask,你把那些請求起來比較耗時(shí)的任務(wù)丟給我,我?guī)湍闾幚恚懔糁Y源去處理下一個(gè)請求吧!很仗義的樣子有木有!只是flask說,好啊,不過,你有地方放嗎?因?yàn)閏elery進(jìn)程也是按照先來后到的原則處理任務(wù),多個(gè)任務(wù)到來,flask也會(huì)來不及處理的時(shí)候。它想到:那就先存起來!不過它自己卻不提供存儲(chǔ)任務(wù)的機(jī)制。所以這個(gè)時(shí)候celery需要一個(gè)中間人,可以將所有任務(wù)統(tǒng)一保存在中間人這里,然后依次處理。這個(gè)中間人,官網(wǎng)上給出了兩個(gè):RabbitMQ 或者 Redis。本教程選擇Redis。

打個(gè)比方,假如有1000個(gè)人同時(shí)注冊你的網(wǎng)站,那你的網(wǎng)站就一直在處理注冊請求,發(fā)送郵件。網(wǎng)站會(huì)一直卡在那里,然后崩潰。所以,需要用到異步發(fā)送郵件??墒且话闱闆r下,我們的網(wǎng)站一年都不會(huì)有1000訪問量。干這個(gè)有什么用??這說的有道理。但是,我手上就有上百萬用戶的數(shù)據(jù)。我可以寫個(gè)腳本,懟到服務(wù)器,什么也不干就24小時(shí)地不停注冊你的網(wǎng)站,直接懟到你把網(wǎng)站關(guān)了!

所以,celery很有必要!
然后我看了下教程。。。。弄了四天。。。踩了好多坑。希望我踩過的坑,能夠幫助準(zhǔn)備入坑的童鞋。

看看我這幾天都經(jīng)歷了些什么

  • cannot connect to amqp

微信截圖_20170608175231.png

](http://upload-images.jianshu.io/upload_images/2577034-4c5402dd3bb71732.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
原因:flask中沒有給celery配置redis,在創(chuàng)建實(shí)例的時(shí)候就要加上redis。
celery = Celery(app.import_name, broker='redis://localhost:6379/0',bckend='redis://localhost:6379/0')

不要像下面這樣,不要像下面這樣,不要像下面這樣

celery = Celery()

  • cannot import name _uuid_generate_random

原因:celery從4.0版本開始就不再支持windows了。。。。。。。。。所以,換系統(tǒng)吧

Windows[](http://docs.celeryproject.org/en/latest/faq.html?highlight=windows#windows)
Does Celery support Windows?[](http://docs.celeryproject.org/en/latest/faq.html?highlight=windows#does-celery-support-windows)
**Answer**: No.
Since Celery 4.x, Windows is no longer supported due to lack of resources.
But it may still work and we are happy to accept patches.
  • 不知道怎么啟動(dòng)worker

flask文檔上寫的啟動(dòng)方式太過簡單,讓人摸不到頭腦

$ celery -A your_application worker
your_application 字符串必須指向創(chuàng)建 celery 對象的應(yīng)用包或者模塊。

這個(gè)我就搞不懂了。比方說我有一個(gè)名為flask的項(xiàng)目,我的所有應(yīng)用放在app這個(gè)包里,然后我要啟動(dòng)的task在一個(gè)叫crawemail的文件里
如果按照教程寫的只想創(chuàng)建celery對象的應(yīng)用或者模塊。那不就成了
$celery -A app worker
但跑起來是這樣的

微信截圖_20170608175231.png

看到?jīng)]有,tasks里是空的,沒有任何東西。所以這樣跑,是不對滴!
再試試
$celery -A app.crawemail worker

微信截圖_20170608175527.png

成功了!任務(wù)懟進(jìn)去了?。?!

但是,接下來還有坑。。。。。

  • 任務(wù)沒跑起來,celery終端一直保持這個(gè)畫面。。。。

這個(gè)就是因?yàn)樯岛鹾醯?,沒有用.delay()函數(shù)啟動(dòng)celery的tasks

  • tasks not register,keyerror
微信截圖_20170608180235.png

這是什么導(dǎo)致的我并不太清楚。但這個(gè)錯(cuò)誤的出現(xiàn)是我單獨(dú)寫了個(gè)只有一個(gè)py文件的flask測試項(xiàng)目運(yùn)行時(shí)候出現(xiàn)的。后來我的解決方法是,再寫一個(gè)文件,用來創(chuàng)建app,然后import他們。
from commontools import app,send_async_email,long_time_def
然后就成功跑起來了

微信截圖_20170608182503.png
  • Error: xxxxx is* not JSON *serializable

原因:把多余的東西傳了進(jìn)delay()函數(shù),所以多余的參數(shù)不要傳。我之前就是send_email.delay(app,msg)
把a(bǔ)pp這個(gè)多余的傳進(jìn)去了所以報(bào)錯(cuò)。

以上是我這四天遇到的坑。。。。
你開上帝視角的話覺得也沒什么啊。。。。。。可你得站在我的角度思考。。。我全程是蒙眼懵逼狀態(tài)啥也不懂
一步一步摸著石頭過河的!
填完這些坑。。。我覺得我好長一段時(shí)間不想再看到celery

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容