iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
佛心分享-SideProject30

打造 APR Engineer 的生產力平台,從 Flow Tracer 到 SignOff DashBoard 的落地實戰系列 第 5

【Day 05】 WinFlow 2.0 演進史:集中管理與分散式架構的抉擇

  • 分享至 

  • xImage
  •  

前言

承接昨天的蘿蔔蹲。接下來要打造的是一套工作流程管理系統。不過在寫第一行程式之前,想先講清楚一件事:

為什麼這個專案是 2.0,而不是把 1.0 再講一遍?

答案已經寫在標題上。1.0 是用 Django 做後端、走集中式管理的 Flow Tracer;2.0 則把鏡頭轉回每一位 APR Block Owner 自己的桌上。

1.0 不是本系列的主角,所以不會著墨太多。但架構抉擇如果只講結論、不講痛過什麼,讀起來會像空口說「這次比較輕量」。文章結尾會附上 1.0 的 Repo,有興趣可以自己翻。

Winflow 1.0 用到了這些材料

項目 技術
後端框架 Django 6.0.1
語言 Python 3
資料庫 SQLite(兩個 DB:default + main)
訊息暫存 Redis(自訂埠 8888)
前端 Bootstrap 5、Bootstrap Icons
Flow 視覺化 Mermaid 10、svg-pan-zoom

看起來就是一套「有網頁、有資料庫、有訊息佇列」的標準後台。當時的目標也很明確:讓很多人在同一個入口提交、同一個螢幕監看。

系統架構

WinFlow 的運作主要分成 5 個部分:主網頁、任務執行檔生成器、Redis、db 寫入器、資料庫 (sqlite3)

┌─────────────────────────────────────────────────────────────┐
│                     Web(Django)                            │
│  /create/  建立任務  →  Task.start()                         │
│  /monitor/ 任務總覽                                          │
│  /task/<uuid>/  DAG 詳情(Mermaid)                          │
└───────────────────────┬─────────────────────────────────────┘
                        │ 產生並執行
                        ▼
┌─────────────────────────────────────────────────────────────┐
│  static/run_script/flow_start/start_<uuid>.sh                │
│       ↓                                                      │
│  static/tool/flow_start.py                                   │
│    · 依 purpose 建立工作目錄與 flow_tree.json                 │
│    · RPUSH 到 Redis db=1,key=start_flow                     │
└───────────────────────┬─────────────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────────────┐
│  Redis(預設 127.0.0.1:8888)                                │
│    db=1  start_flow     新流程定義                           │
│    db=2  stage_update   Stage 狀態更新(預留)               │
│    db=3  flow_update    Task 狀態更新(預留)                │
└───────────────────────┬─────────────────────────────────────┘
                        │ 輪詢消費
                        ▼
┌─────────────────────────────────────────────────────────────┐
│  manage.py db_operator --interval N                         │
│    · 讀取 start_flow → 建立 Stage、寫入 Task.topology        │
│    · stage_update / flow_update 介面已預留                   │
└───────────────────────┬─────────────────────────────────────┘
                        │
                        ▼
┌─────────────────────────────────────────────────────────────┐
│  SQLite                                                     │
│    db/db.sqlite3     Django 預設(auth、sessions…)          │
│    db/main.sqlite3   資料(Task、Stage)                     │
└─────────────────────────────────────────────────────────────┘

使用流程可以收成六步:

  1. 使用者在網頁上填好想跑的 Flow(可以一次好幾個)跟設定,丟進暫存佇列後提交
  2. 伺服端建立這些 Flow 的紀錄,呼叫 Task.start() 啟動
  3. 伺服端生成這些任務會用到的執行檔
  4. 伺服端在工作區建目錄、產生 flow_tree.json,並推入 Redis start_flow
  5. db 寫入器定期消費 Redis,為每個 Stage 產生 UUID、寫進後台 DB
  6. 使用者到 /monitor//task/<uuid>/ 看總覽跟 DAG

我踩過最大的坑:狀態比現實慢了八小時

其中比較大的坑,出在「大量狀態更新」。當時可能同時有數百到數千筆狀態要寫,我一開始沒把 Redis 當 cache,而是直接往 SQLite 硬灌。

結果當然是悲劇——Flow 實際跑完的進度,比網頁顯示的狀態快了整整八個小時 😂

後來的解法很土、也很有效:更新先暫存在 Redis,再由定時批次寫進 SQLite。瓶頸緩過來了,架構也更咬死「Web 不直接扛寫入」。

1.0 應該不錯吧?為什麼還要 2.0

相信你已經發現:1.0 不是讓使用者把工作直接交給 LSF,而是先統一交給「啟動 Server 的那個帳號」,再由該帳號把 Job 送進 LSF。

理論上這沒問題,反正 Job 有出去、有跑完就好(笑)。實務上,APR Block Owner 的權責劃分非常清楚——每個人要全權負責自己的 Block。所有工作如果都從同一隻公用帳號飛出去:

  • bjobs 上看不出這是誰的 place、誰的 route
  • 失敗了不知道該 ping 誰
  • 資源佔用、queue 排隊、誤殺作業,責任會糊成一團

於是這套機制在團隊裡很難推。不是功能不夠,是帳號模型跟組織模型對不上

1.0 的另一個設計初衷,是同時提交、同時監看「上百個 Job」。它最大的價值,是讓多人共用一個入口,代價只是佔用一台機器當 Server。可是一旦團隊當下沒有大量發送 Job 的需求,這個優勢會立刻變薄,露出另外兩條短板:

  • 部署:Django + Redis + 雙 SQLite + 常駐 writer,對「我只想跑自己的 block」太重
  • 建置:新環境要先有人當 Server 管理員,而不是打開工具就能用

因此 2.0 換了一個鏡頭:以每一位 APR Block Owner 的個人視角與需求重新規劃。

不是否定集中管理。是承認:集中管理要養得起一台 Server、一套帳號政策、一個願意當管理員的人。養不起的時候,工具應該縮小到「我的桌面、我的帳號、我的 flow」。

WinFlow 2.0 用了這些材料

項目 技術
語言 Python 3(標準函式庫為主,不靠 pip 套件)
GUI Tkinter 8.6 這一系(常見講法是 8.x;重點是系統自帶)

沒有 Django,沒有 Redis,沒有 Mermaid 前端。狀態不進資料庫,進的是你眼前這份 JSON,以及 LSF 自己的 bjobs

2.0 系統架構:兩個角色,一份契約

2.0 的運作主要就兩塊:使用者互動的 GUI,以及一份描述 Flow 的 JSON。站點預設另外放在 config.json

+-------------+
| config.json |
+-------------+
      |
      v
+-------------+
|  WinFlow2.0 | ---------------------------------
+-------------+             |                    |
      |                     |                    |
      v                     v                    v
+-------------+       +-----------+      +----------------+
| Flow Runner | <---  | flow.json | <--- | Flow Generator |
+-------------+       +-----------+      +----------------+

使用流程可以更短:

  1. 執行 GUI
  2. 切到 Flow Generator:手拉、載入範本、或讀設定,目的都是產出 flow.json
  3. 切到 Flow Runner,按 Run。Runner 依 flow.json 丟 job、盯流程、收結果

跟 1.0 比,少掉的不是「功能清單上的一項」,是整層中介:

  • 不再用資料庫追每個 Job 的狀態
  • 每一個 GUI 實例就是一次獨立的 Flow
  • Job 以使用者本人的名義送進 LSF

責任歸屬因此變清楚。bjobs 上看到的 user,就是這個 block 的 owner。比較不會產生「這是誰丟的、該誰重跑、該誰負責佔 queue」的爭議。

當然也有代價:2.0 不打算當全公司的監控牆。它選擇把「誰在跑什麼」還給 LSF 跟當事人。這是刻意的取捨,不是還沒做完。

小結

  • 1.0 是集中式 Flow Tracer:Web + Redis + SQLite,適合多人海量監看
  • 狀態直寫 SQLite 會讓畫面落後現實;cache 能救效能,救不了部署重量
  • 公用帳號送 LSF,跟 Block Owner 制對不上
  • 2.0 把 Generator 與 Runner 拆開,中間只留 flow.json
  • 每個 GUI 用使用者自己的帳號丟 job:輕、責任清楚、比較推得動

1.0 專案分享

WinFlow1.0


上一篇
【Day 04 】APR Flow 核心概念:其本質就是一場「蘿蔔蹲」
下一篇
【Day 06 】設計專屬你的 Flow:畢竟每家 IC 設計公司的環境都不一樣
系列文
打造 APR Engineer 的生產力平台,從 Flow Tracer 到 SignOff DashBoard 的落地實戰15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言