天天看點

Celery-一個會做異步任務,定時任務的芹菜Celery 分布式任務隊列

比如說你要去一個餐廳吃飯,你點完菜以後假設服務員告訴你,你點的菜,要兩個小時才能做完,這個時候你可以有兩個選擇

一直在餐廳等着飯菜上桌

你可以回家等着,這個時候你就可以把你的電話留給服務員,告訴服務員等什麼時候你的飯菜上桌了,在給你打電話

​ 所謂同步就是一個任務的完成需要依賴另外一個任務時,隻有等待被依賴的任務完成後,依賴的任務才能算完成,這是一種可靠的任務序列。要麼成功都成功,失敗都失敗,兩個任務的狀态可以保持一緻。

​ 所謂異步是不需要等待被依賴的任務完成,隻是通知被依賴的任務要完成什麼工作,依賴的任務也立即執行,隻要自己完成了整個任務就算完成了至于被依賴的任務最終是否真正完成,依賴它的任務無法确定,是以它是不可靠的任務序列。

繼續上面的例子

不管你的在餐廳等着還是回家等着,這個期間你的都不能幹别的事,那麼該機制就是阻塞的,表現在程式中,也就是該程式一直阻塞在該函數調用處不能繼續往下執行。

你回家以後就可以去做别的事了,一遍做别的事,一般去等待服務員的電話,這樣的狀态就是非阻塞的,因為你(等待者)沒有阻塞在這個消息通知上,而是一邊做自己的事情一邊等待。

​ 阻塞和非阻塞這兩個概念與程式(線程)等待消息通知(無所謂同步或者異步)時的狀态有關。也就是說阻塞與非阻塞主要是程式(線程)等待消息通知時的狀态角度來說的

同步阻塞形式

  效率最低。拿上面的例子來說,就是你專心的在餐館等着,什麼别的事都不做。

異步阻塞形式

  在家裡等待的過程中,你一直盯着手機,不去做其它的事情,那麼很顯然,你被阻塞在了這個等待的操作上面;

  異步操作是可以被阻塞住的,隻不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞。

同步非阻塞形式

  實際上是效率低下的。

  想象一下你如果害怕服務員忘記給你打電話通知你,你過一會就要去餐廳看一下你的飯菜好了沒有,沒好 ,在回家等待,過一會再去看一眼,沒好再回家等着,那麼效率可想而知是低下的。

異步非阻塞形式

​ 比如說你回家以後就直接看電視了,把手機放在一邊,等什麼時候電話響了,你在去接電話.這就是異步非阻塞形式,大家想一下這樣是不是效率是最高的  

​ 那麼同步一定是阻塞的嗎?異步一定是非阻塞的嗎?

在實際的軟體開發過程中,經常會碰到如下場景:某個子產品負責産生資料,這些資料由另一個子產品來負責處理(此處的子產品是廣義的,可以是類、函數、線程、程序等)。産生資料的子產品,就形象地稱為生産者;而處理資料的子產品,就稱為消費者。

單單抽象出生産者和消費者,還夠不上是生産者消費者模式。該模式還需要有一個緩沖區處于生産者和消費者之間,作為一個中介。生産者把資料放入緩沖區,而消費者從緩沖區取出資料,如下圖所示:

Celery-一個會做異步任務,定時任務的芹菜Celery 分布式任務隊列

生産者消費者模式是通過一個容器來解決生産者和消費者的強耦合問題。生産者和消費者彼此之間不直接通訊,而通過消息隊列(緩沖區)來進行通訊,是以生産者生産完資料之後不用等待消費者處理,直接扔給消息隊列,消費者不找生産者要資料,而是直接從消息隊列裡取,消息隊列就相當于一個緩沖區,平衡了生産者和消費者的處理能力。這個消息隊列就是用來給生産者和消費者解耦的。------------->這裡又有一個問題,什麼叫做解耦?

解耦:假設生産者和消費者分别是兩個類。如果讓生産者直接調用消費者的某個方法,那麼生産者對于消費者就會産生依賴(也就是耦合)。将來如果消費者的代碼發生變化,可能會影響到生産者。而如果兩者都依賴于某個緩沖區,兩者之間不直接依賴,耦合也就相應降低了。生産者直接調用消費者的某個方法,還有另一個弊端。由于函數調用是同步的(或者叫阻塞的),在消費者的方法沒有傳回之前,生産者隻好一直等在那邊。萬一消費者處理資料很慢,生産者就會白白糟蹋大好時光。緩沖區還有另一個好處。如果制造資料的速度時快時慢,緩沖區的好處就展現出來了。當資料制造快的時候,消費者來不及處理,未處理的資料可以暫時存在緩沖區中。等生産者的制造速度慢下來,消費者再慢慢處理掉。

因為太抽象,看過網上的說明之後,通過我的了解,我舉了個例子:吃包子。

假如你非常喜歡吃包子(吃起來根本停不下來),今天,你媽媽(生産者)在蒸包子,廚房有張桌子(緩沖區),你媽媽将蒸熟的包子盛在盤子(消息)裡,然後放到桌子上,你正在看巴西奧運會,看到蒸熟的包子放在廚房桌子上的盤子裡,你就把盤子取走,一邊吃包子一邊看奧運。在這個過程中,你和你媽媽使用同一個桌子放置盤子和取走盤子,這裡桌子就是一個共享對象。生産者添加食物,消費者取走食物。桌子的好處是,你媽媽不用直接把盤子給你,隻是負責把包子裝在盤子裡放到桌子上,如果桌子滿了,就不再放了,等待。而且生産者還有其他事情要做,消費者吃包子比較慢,生産者不能一直等消費者吃完包子把盤子放回去再去生産,因為吃包子的人有很多,如果這期間你好朋友來了,和你一起吃包子,生産者不用關注是哪個消費者去桌子上拿盤子,而消費者隻去關注桌子上有沒有放盤子,如果有,就端過來吃盤子中的包子,沒有的話就等待。對應關系如下圖:

Celery-一個會做異步任務,定時任務的芹菜Celery 分布式任務隊列

啟動 celery從4.0版本以後就不在支援windows了,如果想在windows環境下使用的話,需要安裝eventlet這個包,啟動的時候需要指定-P eventlet

生産者

模拟兩個消費者

啟動過程跟上面一樣

擷取執行狀态

倘若任務抛出了一個異常, get() 會重新抛出異常, 但你可以指定 propagate 參數來覆寫這一行為:

如果任務抛出了一個異常,你也可以擷取原始的回溯資訊:

支援的參數 :

countdown : 等待一段時間再執行.

eta : 定義任務的開始時間.這裡的時間是UTC時間,這裡有坑

expires : 設定逾時時間.

retry : 定時如果任務失敗後, 是否重試.

retry_policy : 重試政策.

max_retries : 最大重試次數, 預設為 3 次.

interval_start : 重試等待的時間間隔秒數, 預設為 0 , 表示直接重試不等待.

interval_step : 每次重試讓重試間隔增加的秒數, 可以是數字或浮點數, 預設為 0.2

interval_max : 重試間隔最大的秒數, 即 通過 interval_step 增大到多少秒之後, 就不在增加了, 可以是數字或者浮點數, 預設為 0.2 .

其實celery也支援linux裡面的crontab格式的書寫的

繼續閱讀