首先,一些背景資訊:我不是 IT 專業人士。我在工廠生產線上工作,在業餘時間自學了所有這些知識,純粹出於興趣——所以請假設我沒有正式背景,如果有什麼不夠深思熟慮的地方,請不要客氣指出。
我為一家工廠構建了一個小型 MES(製造執行系統),我想從認真使用 n8n 的人那裡獲得誠實的現實檢查,因為我可能在將它推向遠超其預期用途的方向。
該設置。一家小型工廠在生產線上組裝機器。每個單位要經過 6 條線上的 5 個部門。大約有 30 個車間終端(亭式瀏覽器),每個工作站一個。
該架構。n8n 是一切的中心。操作員看到的每個頁面都是在 n8n Code 節點內生成的 HTML,並通過 Respond to Webhook(Content-Type: text/html)返回。PostgreSQL 保存數據。這些頁面不僅僅是視圖:操作員點擊按鈕,調用其他 n8n webhook 來推進機器的狀態(一個有約 8 個動作的狀態機)、寫筆記、阻止/解除阻止單位等。所以 n8n 提供的是整個前端,而不僅僅是自動化。
存取模型。根據設計,沒有登錄。這是一個受信任的車間;權限在 URL 中傳遞(「鏈接就是權限」),按鈕只在狀態和來源允許的地方顯示。在這個背景下是合理的,但不太常規。
預期負載。適度的。大約 30 個終端,在任何給定時刻只有少數操作員在操作。動作發生在分鐘級別,而不是高頻。每年幾千台機器,約 40k 個狀態事件/年。概覽頁面將每 1-3 分鐘自動刷新一次。
我的問題。在這個規模上,從 n8n webhook 提供整個交互式 UI 是否是一個可以辯護的選擇,或者我在濫用這個工具?具體來說:
隨著這個系統的增長,首先會出現什麼問題——執行歷史、性能、可維護性?
你會將其分離(專用前端 + n8n 作為後端 API)嗎?如果目前的方案已經有效,這樣做值得嗎?
有人實際上在生產中運行過類似的東西嗎,或者這是一個已知的反模式?
我真的很想聽到「不要這樣做,原因是……」,而不是禮貌的鼓勵。謝謝。
描述問題/錯誤/問題
錯誤訊息是什麼(如果有的話)?
請分享你的工作流程
(在畫布上選擇節點,使用鍵盤快捷鍵 CMD+C/CTRL+C 和 CMD+V/CTRL+V 來複製和粘貼工作流程。)
分享最後一個節點返回的輸出
關於你的 n8n 設置的信息
- n8n 版本:
- 數據庫(預設:SQLite):
- n8n EXECUTIONS_PROCESS 設置(預設:own、main):
- n8n 運行方式(Docker、npm、n8n cloud、桌面應用):
- 操作系統:
嗨 @Folpe77 歡迎!
執行歷史記錄首先崩潰,而且是無聲地崩潰。每次頁面渲染和每次自動刷新都會保存一個 webhook 執行,所以 30 個終端每 1 到 3 分鐘刷新一次,每天會產生大約 15k 到 40k 次執行,而你的年度狀態事件約為 ~40k。EXECUTIONS_DATA_PRUNE_MAX_COUNT 默認為 10000,所以日誌每天會循環幾次,你實際想追蹤的狀態變化在幾小時內就消失了。
按角色分割而不是分割前端:在自己的工作流中進行頁面渲染,並將「保存成功的生產執行」設置為「不保存」,狀態機器在單獨的工作流中保持保存。渲染量就不再重要了,審計跟蹤也能保存下來。
在這個負載下,n8n 可以處理流量,但我不會在生產環境中保持目前的信任模型不變。
主要風險不是原始吞吐量,而是授權、並行性和可維護性:
- URL 是持有者憑證。它可能會透過瀏覽器歷史記錄、螢幕截圖、日誌、引薦人或書籤洩露。至少要使用與終端機 + 動作相關的短期簽署令牌,在伺服器端驗證,並保持網路分段。絕對不要僅依賴隱藏按鈕——Webhook 必須授權每個狀態轉換。
- 在 PostgreSQL 中為每個狀態變更建立一個交易。只在目前狀態/版本與操作者看到的內容相符時更新(樂觀鎖定),然後返回衝突,而不是無聲地覆蓋較新的動作。
- 如 Anshul 所建議,將工作流程呈現與命令工作流程分開。禁用成功執行的已保存內容以供讀取,短期內保留失敗的執行,並在專用稽核表中保留狀態變更事件,而不是依賴 n8n 執行歷史記錄。
- 將狀態轉換規則放在一個可重複使用的子工作流程或資料庫函數中。在許多程式碼節點中生成 HTML 將成為第一個可維護性問題。
- 在擴展使用之前,新增健康狀態檢查、錯誤工作流程、資料庫備份和一個小型協調工作。
我不會立即重寫一個運作良好的低負載系統。我首先會強化授權和交易式寫入,隔離讀取與命令工作流程,並測量延遲/錯誤率。當 UI 迭代、離線行為、更豐富的驗證或多個開發人員使嵌入式 HTML 變得困難時——而不是單純因為 30 個資訊亭對 n8n 來說太多——單獨的前端才變得值得。
執行歷史(「無聲殺手」) n8n 的設計是記錄每一次執行。在標準自動化中,工作流程可能每小時執行一次。但在你的設置中,每次頁面重新整理和每次按鈕點擊都是一次執行。
- 風險: 你的 n8n 資料庫會快速膨脹。即使啟用了修剪功能,為每次 UI 互動都寫入「成功」到資料庫的開銷最終也會拖慢整個系統。你會注意到 UI 變得「反應遲鈍」,不是因為 HTML 速度慢,而是因為執行引擎苦於記錄事件。
可維護性(「程式碼節點噩夢」) 在 JavaScript 程式碼節點內寫入 HTML 是自找麻煩。
- 風險: 你沒有語法高亮顯示、沒有「即時預覽」,也無法輕鬆管理 CSS/樣式。當你新增第 9 個或第 10 個狀態動作時,你的程式碼節點會變成巨大的文字牆。單一遺漏的
</div> 或字串中的拼寫錯誤就會導致整個頁面崩潰,而在小小的 n8n 視窗內進行除錯是痛苦的。
效能與延遲 n8n 是一個編排引擎。當請求到達 webhook 時,n8n 必須初始化工作流程、透過節點移動資料,然後回應。
- 風險: 這比專用網頁伺服器慢好幾個數量級。對於 30 個終端機來說還可以。如果你以後要擴展到 100 個終端機或新增高頻率更新,點擊按鈕和看到頁面重新整理之間的「延遲」將令操作人員感到沮喪。
是的。絕對值得。 但你不必成為全端開發者才能做到。
「可防禦」的架構應該是:
- 前端: 一個專用 UI,知道如何顯示資料和傳送請求。
- 後端: n8n 作為 JSON API。你的 n8n 工作流程應該傳回原始資料(JSON),而不是 HTML。
為什麼值得?
- 即時 UI: 前端可以立即更新按鈕顏色或狀態標籤,無需從伺服器重新載入整個頁面。
- 穩定性: 如果你想改變頁面的版面配置,就不用去動 n8n 中的「商業邏輯」。
- 執行效率: 對於簡單的 API 呼叫,你可以將 n8n 工作流程設定為 「保存執行:無」,這樣完全消除了資料庫膨脹。
實際的決定方式是在重寫任何東西之前執行一個小型的「生產演練」。
挑選一個重要的狀態轉換,例如「阻止/解除阻止單位」,並驗證三件事:
- 兩個終端幾乎同時點擊時,無法互相覆蓋。
- 陳舊的頁面無法執行不再有效的動作。
- 即使 n8n 執行歷史被修剪,該事件稍後仍然可以被審計。
如果這三點都成立,當前架構在你的規模下可能是防禦得當的,同時你可以逐步強化它。如果不成立,第一次分割不應該是「新前端」;而應該是將狀態轉換移至更安全的交易層,並讓 n8n 在其周圍進行編排。
@Folpe77 你的 1–3 分鐘自動刷新概覽頁面本身就是一個獨立於執行日誌的擴展風險,輪詢無法在下一次刷新前告知操作者狀態變化,所以當你增加行數時,你會想要縮短間隔,這會迅速增加 webhook 負載。一個廉價的修復方案,不需要完整的前端重寫:繼續從 n8n 提供 HTML,但將輪詢替換為 Server-Sent Events 或輕量級 WebSocket 中繼(甚至只是一個專用於推送的小型獨立 Node 進程),由 n8n 在狀態變化時觸發,終端會立即更新,你也會削減大部分直接命中 n8n 的「讀取」流量。
@Anshul_Namdev 的診斷完全正確——將頁面渲染與狀態機分開,保持狀態機的儲存功能。值得具體說明這樣做能帶來什麼:一旦該歷史表成為現場發生事情的真實記錄,下一個問題就是是否有任何東西能阻止它稍後被悄悄編輯——不良遷移、直接資料庫存取、下遊某處的錯誤。一個普通的表意味著它沒有被觸及,但不能證明它。
另外,對於你的狀態機的批准方面——阻止/解除阻止、簽核,無論什麼需要人工介入:有一個模式是在工作流發布時為每個工作流生成一個 webhook URL,而不是每個請求生成一個。該工作流的每個批准事件都會落在同一個 URL 上,只在實際到達時才開始新的執行,所以沒有任何東西會開啟等待,也沒有任何東西會像 Anshul 所描述的那樣在等待中途被修剪的風險。我已經構建了一個通用版本——不是 AI 代理特定的,對於像你這樣的人工驅動的狀態機也同樣適用。如果有用的話,很樂意分享