Jepsen 測 Orkes Conductor:故障下工作流會消失、重複執行或假完成
Jepsen · 2026-10-20
Orkes Conductor 宣稱的保證是 at-least-once 投遞,且工作流最終會到達終止狀態,但 Jepsen 在 5.3.2 到 5.5.0-rc2 之間找到了讓工作流消失、永遠卡在 RUNNING、或沒執行任務就被標成 COMPLETED 的路徑。這份由 Kyle Kingsbury 撰寫、Orkes 出資的分析共列出 9 個問題,修補集中在 5.5.0 與 5.5.6。
測試設定
Conductor 源自 Netflix,架構是無狀態的 server,加上資料庫(Postgres、Cassandra 或 Redis)與佇列(常用 Redis)。本次只測 Postgres 搭配 Redis,在十個 Debian 節點上跑,並注入程序暫停、kill 與網路分區。
負載很簡單:一個只有單一任務的 workflow,任務睡最多 30 秒並回傳隨機輸出,由測試框架檢查重複執行、遺失、永不啟動與 null ID 等異常。測試版本包含 5.3.2、5.4.0、5.5.0-rc1、5.5.0-rc2。
資料遺失與假完成
遺失的工作流(#7):server 在已提交的工作流上入列失敗,卻接著把 Postgres 裡的紀錄刪掉。在一次 5.4.0 測試中,某個工作流可見 74 秒,之後一路回傳 null/404。5.5.0 改為入列失敗時不再刪除。
被遺棄的工作流(#5):工作流寫進 Postgres 卻沒進 decider 佇列,會永遠停在 RUNNING。5.5.0 新增背景重新入列程序。
沒執行的完成(#9):5.5.0-rc2 出現 3 個工作流在任務未跑的情況下被判完成。重試時舊任務被寫上 superseded 標記,新任務紀錄卻沒寫成功,sweeper 因此認定工作流已結束。5.5.6 讓失敗的重試寫入浮出錯誤。
重複執行與錯誤語意
在健康叢集(2 台 server、3 個 worker、約每秒 1,100 個 workflow、預設 1 分鐘 lease)中,同一個任務大約每六小時會同時在兩個 worker 上執行(#1)。把 lease 縮到 1 秒,頻率升到每幾分鐘一次,另有 sweeper 的 time-of-check/time-of-use 缺陷推波助瀾,5.5.6 已修。
另一個影響大的是 #6:一次短測試裡,25,920 次失敗的 startWorkflow 呼叫中有 1,752 次其實已建立工作流。原因是 client 對非冪等請求重試,最後只回報最新一次的「連線失敗」。Java SDK 以 PR 175 改為不重試非冪等請求,但 Jepsen 仍列為未解。
| 問題 | 影響版本 | 狀態 |
|---|---|---|
| #5 被遺棄 | 5.3.2、5.4.0、5.5.0-rc1 | 5.5.0 修 |
| #7 遺失 | 5.3.2 至 5.5.0-rc1 | 5.5.0 修 |
| #9 假完成 | 5.5.0-rc2 | 5.5.6 修 |
| #2 啟動前卡住 | 多版本 | 依設計,未改 |
其餘還有 #4(分區管理競態使 SQL 變成 INSERT INTO null,5.5.6 修)、#3(startWorkflow() 偶爾回傳 null,原因不明,Java client 6.0.2 有緩解)。
影響範圍
跑自管或託管 Conductor、且用 Postgres 加 Redis 的團隊,先升到 5.5.6。報告建議用實際資料審計舊叢集:找出長時間沒進展的 RUNNING 工作流(#5),以及任務根本沒跑卻是 COMPLETED 的工作流(#9),再重啟。消失的工作流(#7)可能得靠上游日誌還原。
應用端要把所有 Conductor 錯誤視為「結果不確定」,因為失敗的呼叫可能已成功。任務必須冪等;有 failure workflow 時效果還可能被重排,報告建議用 idempotency key 與邏輯時鐘。#2 的卡頓則可降低 responseTimeoutSeconds(預設一小時)來縮短。
限制也要記得:只測了 Postgres 與 Redis,沒涵蓋多步驟工作流、operator、failure workflow、高延遲與時鐘偏移。Jepsen 只能證明 bug 存在,不能證明沒有。