特么的。。。寫好的東西不見了一半。。。又得重寫。。
星期一開始,有同事和我說要不要把我們的項目加上celery,異步發送郵件。我想了想這塊我沒碰過,正好學點新東西。
celery是干什么的,我這里抄點別人的文字
###來源 http://www.ziyoubaba.com/archives/590
flask是一個阻塞式的框架。這里的“阻塞”是指flask處理請求的時候,一次只能處理一個,當多個requests過來,flask會說,大家不要急,一個一個來。如果恰好這時候某個請求耗費了大量的時間(種種原因),在這段時間內,flask說:我忙著呢,后來的排好隊。然后服務進程被占用著,后來的請求得不到處理。這就叫做被阻塞住了。說得再多不如一只栗子:
def long_time_def():
for _ in range(10000):
for j in range(10000):
i = 1
return 'hello'
我的老爺機運行這只函數需要大約8s的時間,可以很好地用來充當“阻塞俠”的角色。如果你的本配置比較好,可以適當增大數字。然后我們這么構建一個flask服務端:
### flask_celery.py ###
app = Flask(__name__)
@app.route("/")
def hello():
print ("耗時的請求")
result=long_time_def()
return result
@app.route('/t')
def test():
return 'test!'
if __name__ == "__main__":
app.run(debug=True)
運行一下,同時訪問‘/’與‘/t’你就能明白,當‘/’未返回結果的時候,‘/t’是沒有響應的。
多進程的方案只能說可以緩解這種“阻塞”,但無法根治,因為進程有限,訪問量不可控,早晚所有進程都被阻塞。所以一個分布式的任務隊列框架被搬上臺面:celery。
celery會這么說:flask,你把那些請求起來比較耗時的任務丟給我,我幫你處理,你留著資源去處理下一個請求吧!很仗義的樣子有木有!只是flask說,好啊,不過,你有地方放嗎?因為celery進程也是按照先來后到的原則處理任務,多個任務到來,flask也會來不及處理的時候。它想到:那就先存起來!不過它自己卻不提供存儲任務的機制。所以這個時候celery需要一個中間人,可以將所有任務統一保存在中間人這里,然后依次處理。這個中間人,官網上給出了兩個:RabbitMQ 或者 Redis。本教程選擇Redis。
打個比方,假如有1000個人同時注冊你的網站,那你的網站就一直在處理注冊請求,發送郵件。網站會一直卡在那里,然后崩潰。所以,需要用到異步發送郵件。可是一般情況下,我們的網站一年都不會有1000訪問量。干這個有什么用??這說的有道理。但是,我手上就有上百萬用戶的數據。我可以寫個腳本,懟到服務器,什么也不干就24小時地不停注冊你的網站,直接懟到你把網站關了!
所以,celery很有必要!
然后我看了下教程。。。。弄了四天。。。踩了好多坑。希望我踩過的坑,能夠幫助準備入坑的童鞋。
看看我這幾天都經歷了些什么
-
cannot connect to amqp
](http://upload-images.jianshu.io/upload_images/2577034-4c5402dd3bb71732.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
原因:flask中沒有給celery配置redis,在創建實例的時候就要加上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了。。。。。。。。。所以,換系統吧
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.
-
不知道怎么啟動worker
flask文檔上寫的啟動方式太過簡單,讓人摸不到頭腦
$ celery -A your_application worker
your_application 字符串必須指向創建 celery 對象的應用包或者模塊。
這個我就搞不懂了。比方說我有一個名為flask的項目,我的所有應用放在app這個包里,然后我要啟動的task在一個叫crawemail的文件里
如果按照教程寫的只想創建celery對象的應用或者模塊。那不就成了
$celery -A app worker
但跑起來是這樣的
看到沒有,tasks里是空的,沒有任何東西。所以這樣跑,是不對滴!
再試試
$celery -A app.crawemail worker
成功了!任務懟進去了!!!
但是,接下來還有坑。。。。。
-
任務沒跑起來,celery終端一直保持這個畫面。。。。
這個就是因為傻乎乎的,沒有用.delay()函數啟動celery的tasks
-
tasks not register,keyerror
這是什么導致的我并不太清楚。但這個錯誤的出現是我單獨寫了個只有一個py文件的flask測試項目運行時候出現的。后來我的解決方法是,再寫一個文件,用來創建app,然后import他們。
from commontools import app,send_async_email,long_time_def
然后就成功跑起來了
-
Error: xxxxx is* not JSON *serializable
原因:把多余的東西傳了進delay()函數,所以多余的參數不要傳。我之前就是send_email.delay(app,msg)
把app這個多余的傳進去了所以報錯。
以上是我這四天遇到的坑。。。。
你開上帝視角的話覺得也沒什么啊。。。。。。可你得站在我的角度思考。。。我全程是蒙眼懵逼狀態啥也不懂
一步一步摸著石頭過河的!
填完這些坑。。。我覺得我好長一段時間不想再看到celery