iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Software Development

Temporal 開發指南:掌握 Workflow as Code 打造穩定可靠的分散式流程系列 第 7

Day07 - 分散式流程可靠性的基石 - State Persistence & Replay

  • 分享至 

  • xImage
  •  

State Persistence = Event History

https://ithelp.ithome.com.tw/upload/images/20250921/20141146qIcQp9c6Zo.png

僅有狀態機概念還不夠,流程必須能被「保存與還原」。Temporal 為每個 Workflow Instance 維護一份獨立的 Event History:

  • 記錄每一步的決策與結果 (指令、輸入、輸出、計時器、Activity 開始/完成等,參考上圖)
  • 讓流程具備可追蹤與可稽核性
  • 但光有事件記錄還不夠,系統還需要一個機制,能把這些事件重新帶入 Workflow 程式碼,讓流程精確地還原到中斷點。這個機制就是 Replay。

Replay = Event History + Workflow Code

Replay 的核心是:讀取 Event History,驅動 Workflow 程式碼重播,將流程還原到中斷點。

  • 先回填先前的輸入與決策,再按事件順序推進
  • 遇到 Activity/Timer 等副作用事件,若歷史已有結果,SDK 直接回放,不會再次執行副作用
  • 直到重播到最新事件為止,流程可無縫續跑

https://ithelp.ithome.com.tw/upload/images/20250921/201411467IRSu5HAr4.png

以上圖為例,當程式執行到:

  1. 第一個活動 acts.registerOriginal(req),Worker 會比對 Event History,若已存在 ActivityTaskCompleted,則直接回放結果,不會再次呼叫外部服務。
  2. 第二個活動 processImage 在 Event History 中為 ActivityTaskScheduled → ActivityTaskTimedOut
    • 這表示 Workflow code 呼叫了 acts.processImage(req),但該活動在實際執行時因逾時而失敗。
    • 是否重試或補償取決於設定的 retry policy 與流程邏輯。

Deterministic Workflow

Workflow 必須是確定性的(Deterministic):給定同一份 Event History,重播必須產生相同的決策與結果。為了維持決定性:

  • 避免直接使用非決定性來源(系統時間、隨機數、非序列化的外部狀態)
  • 在 Workflow 中不做外部 I/O;外部互動交給 Activity 或以 Signal/Update 注入
  • 避免依賴不穩定的迭代順序(例如未排序的 Map/Set)

常見反例與修正

https://ithelp.ithome.com.tw/upload/images/20250921/201411469G4CnLJSVd.png

  • 直接呼叫外部服務:如前面給的例子,改由 Activity 執行外部 I/O,結果會寫入 Event History 以便重播
  • 取得當前時間:不要直接讀系統時間;改用 SDK 的時間 API,例如 Java: Workflow.currentTimeMillis()
  • 產生隨機數:不要直接 new Random()/Math.random();改用 SDK 提供的決定性隨機或將隨機性放到 Activity 並回傳結果
  • 版本演進時使用 SDK 提供的版本化機制(如 getVersion/patch),讓新舊程式能同時安全重播

接下來,當我們把「Event History」與「Deterministic Workflow」結合起來,就能觀察一個 Workflow 在實際運行時的完整軌跡。這條軌跡正是 Workflow 的生命週期:從啟動、決策推進,到活動執行與結果回填,再回到推進,直到最終完成。

Workflow 生命週期(概要)

https://ithelp.ithome.com.tw/upload/images/20250921/20141146bknynSj6UR.png

上圖正好呈現標準的生命週期,可以在往前比對 Event History 是不是就照著這個生命週期在走:

  1. 啟動流程
    • WorkflowExecutionStarted
    • Runtime 建立 workflow instance,開始進入事件記錄模式。
  2. 流程推進(Workflow Task Execution)
    • WorkflowTaskScheduled → WorkflowTaskStarted → WorkflowTaskCompleted
    • Worker 取出「Workflow Task」執行決策邏輯(workflow code),再把決策結果(例如要啟動哪些 activity)寫回 history。
  3. 執行活動(Activity Execution)
    • ActivityTaskScheduled → ActivityTaskStarted → ActivityTaskCompleted
    • Worker 執行 activity(真實的 I/O 或業務邏輯),結果再寫回 history。
  4. 回到流程推進
    • Workflow 讀取 activity 的結果,再進行下一步邏輯。這會再產生新的 Workflow Task Execution 週期。
  5. 結束流程
    • 當邏輯完成,進入 WorkflowExecutionCompleted,整個 workflow lifecycle 結束。

結語

透過 Event History、Replay 與 Deterministic Workflow,我們理解了 Temporal 如何確保流程能被精準保存與還原,並在生命週期中持續向前推進。
不過,這只是可靠性的基礎。真正投入生產環境,還有問題需要被解決:ordering、idempotency、error handling、timeout、retry policy、concurrency 與 rate control。
接下來,我們將從這些面向切入,探討在分散式系統中如何進一步確保工作流的健壯性與可預測性。


上一篇
Day06 - 分散式流程的核心觀念 - BASE Model / State Machine
下一篇
Day08 - 分散式流程的順序性(Ordering)挑戰
系列文
Temporal 開發指南:掌握 Workflow as Code 打造穩定可靠的分散式流程9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言