序列文章:
-
Celery 源碼解析一:Worker 啟動流程概述
-
Celery 源碼解析二:Worker 的執行引擎
-
Celery 源碼解析三: Task 對象的實現
-
Celery 源碼解析四: 定時任務的實現
-
Celery 源碼解析五: 遠程控制管理
-
Celery 源碼解析六:Events 的實現
-
Celery 源碼解析七:Worker 之間的交互
-
Celery 源碼解析八:State 和 Result
在前面幾篇解析中,我們已經看過了 Worker 是如何運行的,Task 是如何創建的,以及怎么被路由到 Worker 中,除了這些之外,我們還對流量限制,Worker 控制和 Task/Worker 產生和處理 Event 進行了介紹。但這卻不是全部,今天我將繼續和大家一起來看看 Celery 的 Task Result 和 State 相關的內容。
Task State
在 celery/celery/states.py 中,可以看到 Task 的所有 State

至於如果想要看 Task 的狀態轉變,那我們就需要回顧一下 Task 從產生到完成的過程,如果是一個普通的 Task 的話,那么它的執行流程應該是:
從 Producer 產生 -①-> MQ -②-> Consumer 接收 -③-> 執行策略執行 -④-> 執行完成
那么這里的 ①②③④ 有沒有設置狀態,並且狀態是啥,就是我們關注的重點了,ok,那我們就跟隨之前的腳步快速得發掘一番:

這個是同步發送消息的時候,其實也是第一次出現 state 的時候,但是這個 state 已經是 ④ 之后的狀態了,但是,無妨,我們已經知道了執行完成之后的狀態是在這里 update 的。那么對於異步的情況又是如何更新狀態的呢,那根據我們之前的 review,我們知道應該去找 AsyncResult:

所以這里就是 backend 的事情啦,backend 再甩鍋給 backend Consumer,然后就是在 backend Consumer 里面干活了,最后就到了這:

這里其實雖然是調用的 on_state_change 但是,我們應該知道的一點就是在這個時候其實狀態已經變化了,那么我們就應該追述到上面的 result._iter_meta,看看里面的實現,這里我就飄過很多細節了,直接看最實際的地方:

這里可以發現,其實結果是通過 Backend 組件完成的,例如 Redis 就放在 Key 對應的 Value 中,其他的 Backend 也類似,如果沒有的話,在 Line 667 我們就知道了,狀態就是 PENDING 啦,第二個狀態捕獲!然后還有 Line 668 這里的解析結果也是值得我們一看,我直接看最后吧:

可以發現這里也是很有趣的,如果 Task 的狀態是異常狀態的話,還需要進行異常回溯,其實就是把異常信息解壓出來,展示給我們看。
那我們是時候我們去找找第三個狀態:Received 了,我們可以猜測一下大概可能出現的位置,這里就是:

這里可以發現居然是有一個 EVENT 發送出去,然后我們就應該去看看處理這個 Event 的人啦,如果你還有印象的話,那么你應該可以很容易得追蹤到:

這里你會發現你感興趣的所有東西,哈哈,其實你需要看看一個字典:

你會發現所有的狀態都可以在這里更新,哈哈。所以下面我就列一下各個 EVENT 的發出地點就好了:

如果你夠細心的話,你會發現 failed 和 succeeded 都是有兩處發送地點,有興趣猜測一下原因么?
Task Result
其實在前面說 State 的過程中我們已經看到了很多和 Result 有關的東西了。Result 可以認為就兩種,同步和異步的,其實也可以看成一種;但是,從另一個維度看,Result 其實也可看成成功的和失敗的,anyway,這些都是在 Result 中保存了的。
我在這里就簡單回顧看看 第三篇 中看過的內容,其實 Result 中就放了這幾樣東西:

分別是 任務ID、返回值、執行狀態 以及 錯誤堆棧信息,我們在調用的地方用這些信息就足夠了。
Worker State
除了 Task 有狀態之外,Worker 其實也是有狀態的,回顧我們 第一篇 的內容,Worker 的啟動過程這么冗長,所以不是說一運行就到了 Runing 狀態了,中間肯定是有各種狀態的,所以我們不妨一起來看看。
回顧一下我們之前看的一些代碼,我們應該是有講過一個叫做 HeartBeat 的組件,它的作用就是保持發送心跳,告訴其他 Worker 這個 Worker 還活着,那么這是一種狀態,除了這些狀態之外,我們還可以找到的其他 Worker 狀態有:
- worker-offline
- worker-online
- worker-heartbeat
Worker-heartbeat 我們很清楚它在哪里發送出去的了,那么 Worker-online 和 Worker-offline 又是在哪里發出去的呢?其實都一樣的,我們看到 Heart 這個 Bootstep:

着重看看 start 和 stop 方法,我們會發現其實調用的都是同一個地方:

一切了然於胸!
