n8n 雲端實例工作流程當機

描述問題/錯誤/問題

n8n 雲端實例工作流程崩潰。

我的工作流程在過去 3 個月一直運行順利,但昨天突然失敗了 3 次,n8n 自動將其關閉。曾經有過系統在超過 30 次執行中失敗但從未關閉的情況。但這次在 3 次後就被關閉了。另外,我在失敗的節點上重試了 3 次,但由於記憶體空間不足,它仍然崩潰了。根據文件,n8n 應該會自動重啟實例,但那也沒有發生,我在今天手動重啟了它。我可以採取什麼預防措施來應對未來的情況?

錯誤訊息是什麼(如果有的話)?

執行在此節點停止

n8n 在執行此流程時可能已耗盡記憶體。更多背景資訊和如何避免這種情況的提示在文件中

請分享你的工作流程

(選擇畫布上的節點,使用鍵盤快速鍵 CMD+C/CTRL+C 和 CMD+V/CTRL+V 來複製和貼上工作流程。)

分享最後一個節點返回的輸出

關於你的 n8n 設定的資訊

  • n8n 版本:
  • 資料庫(預設:SQLite):
  • n8n EXECUTIONS_PROCESS 設定(預設:own、main):
  • 透過以下方式執行 n8n(Docker、npm、n8n cloud、桌面應用程式):
  • 作業系統:

@Aarush_Bisht

為了防止記憶體相關的當機,您應該專注於減少資料在工作流程中移動時的「記憶體佔用量」。

A. 實施批次處理(最重要的步驟) 如果您正在處理大量項目列表(例如,來自資料庫或 API 的 1,000+ 列),請勿一次將它們全部傳遞到下一個節點。

  • 使用「分批分割」節點: 以較小的塊為單位處理項目(例如,每次 50 或 100 個)。這確保 n8n 在任何給定時刻只會在活躍記憶體中保存少量資料。

B. 避免在記憶體中保存「沉重」的資料

  • 限制欄位: 使用 Set 節點Edit Fields 節點在工作流程早期移除不必要的資料。如果 API 返回 50 個欄位,但您只需要 3 個,請立即刪除其他 47 個。
  • 二進位資料處理: 如果您正在處理大型檔案(PDF、圖像),請避免在工作流程流中保存多份二進位資料副本。使用「讀取/寫入二進位檔案」節點或外部儲存空間(如 S3 或 Google Drive),並僅在節點之間傳遞檔案 ID/URL。

C. 最佳化節點執行

  • 避免大型迴圈: 深層嵌套迴圈或遞迴呼叫會快速消耗堆疊和堆積記憶體。
  • 等待節點: 如果您在迴圈中呼叫 API,請新增 Wait 節點(即使只有 1 秒)。這不僅可以防止速率限制,還可以讓 Node.js 垃圾收集器有機會清除未使用的記憶體。

D. 監控和警示

  • 錯誤工作流程: 建立一個專用的「錯誤工作流程」(透過工作流程設定),在發生故障時立即發送 Slack 或電子郵件通知。這允許您在系統達到「斷路器」限制並關閉工作流程之前手動介入。

它已經正常運作了好幾個月,但在 3 次不同的執行失敗後某一天就當機/取消發布了。(我已經為每次執行的節點實現了 3 次重試)。資料量也不大(字面上只是 50-60 行員工資料)。我也已經實現了錯誤處理,我做了「始終輸出資料」,然後如果偵測到錯誤就通知我。有趣的是它也沒有遵循那個邏輯。既沒有嘗試重試,就直接失敗並取消發布了。

有任何以下情況適用嗎:

  • **突然出現大型承載量:**那 60 位員工中有人的欄位(例如「備註」或「簡介」部分)是否突然包含大量文字或龐大的 base64 編碼圖片/檔案?
  • **API「無限」回應:**您呼叫的外部 API 是否為其中一筆記錄傳回龐大的 JSON 物件(例如 10MB 以上)?
  • **循環參考:**資料是否產生迴圈,導致 JavaScript 引擎達到「堆疊溢位」或「記憶體不足」限制?

檢查您的雲端記錄

  1. **檢查執行歷史記錄:**尋找 3 個失敗的執行。它們的狀態是 Error 還是只是 Running(卡住)或完全遺失?如果在工作流程已關閉的情況下它們遺失或卡在「執行中」狀態,即可確認發生硬體當機。
  2. **檢查資料:**查看昨天進入工作流程的資料。將其與前幾天進行比較。尋找這 60 行中任何異常龐大的字串或意外格式。
  3. 檢查「沉重」節點:您是否有任何代碼節點?代碼節點中的小邏輯錯誤(例如無限 while 迴圈)可能在幾秒內耗盡所有可用 RAM,繞過所有 n8n 的內建錯誤處理。

50-60 行資料對應一名員工。
而失敗的 3 個中,其中一個是 JavaScript 程式碼節點,我當時正在嘗試降低資料的維度。
{
“nodes”: [
{
“parameters”: {
“jsCode”: “\nconst updates = $node[“Webhook”].json.body.data.fieldUpdatesIds.map(f =\ f.id);\n\nconst targetFields = [\n “work.site”,\n “work.department”,\n “work.siteId”,\n “work.customColumns.column_1732603686850”,\n “work.workChangeType”,\n “work.title”,\n “work.activeEffectiveDate”,\n “work.reportsTo”,\n “root.displayName”\n];\n\nconst check = updates.some(id =\ targetFields.includes(id));\n\nreturn [{ check}];\n”
},
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
-3104,
496
],
“id”: “7e8b7768-aa58-4218-98bb-24008a7ea4ef”,
“name”: “Code in JavaScript1”
}
],
“connections”: {
“Code in JavaScript1”: {
“main”: [

]
}
},
“pinData”: {},
“meta”: {
“instanceId”: “0f39d8fdd402ddce20d0eb724526828e8c2d8679170e3a08fe6cd471c799fab6”
}
}

那 3 次執行的日誌無法檢查,因為 n8n 說由於執行失敗,日誌沒有被保存。(很奇怪,因為失敗的日誌反而更重要)。
1 個節點失敗,該節點只是用來取得認證令牌,沒有迴圈,就只是一次 API 呼叫。第三個(HTTP 節點)在回應中有一些 imageUrls,但沒有圖片(根據之前的執行結果)。這 3 個都在 3 次不同的執行中同時失敗,原因相同。

這可能是 n8n 伺服器端的某個故障嗎?

非常不可能。

你的程式碼在邏輯上很簡單,不應該導致有 60 行資料的伺服器當機。然而,它在存取資料的方式上存在效能風險

const updates = $node["Webhook"].json.body.data.fieldUpdatesIds.map(f => f.id);

使用 $node["NodeName"] 會強制 n8n 在整個工作流程期間將該前一個節點的完整資料物件保留在作用中的記憶體堆中。如果你的 Webhook 承載很大,且你有多個節點這樣做,你會成倍增加記憶體使用量。

用這個版本取代你目前的 JS 程式碼。它使用了現代語法,並新增了「安全檢查」來防止節點在資料遺失時當機(否則會導致 TypeError):

// 使用現代的 $(…).item 語法以更好地管理記憶體
const webhookData = $("Webhook").item.json.body?.data?.fieldUpdatesIds;

if (!Array.isArray(webhookData)) {
    return [{ check: false, error: "No fieldUpdatesIds found" }];
}

const updates = webhookData.map(f => f.id);

const targetFields = [
 "work.site",
 "work.department",
 "work.siteId",
 "work.customColumns.column_1732603686850",
 "work.workChangeType",
 "work.title",
 "work.activeEffectiveDate",
 "work.reportsTo",
 "root.displayName"
];

const check = updates.some(id => targetFields.includes(id));

return [{ check }];

為了確保在出現問題時確實能取得日誌:

  1. 前往工作流程設定(齒輪圖示)。
  2. 確保**「儲存失敗的執行」**已開啟。
  3. 將**「儲存成功的執行」設為關閉**(或「僅在有錯誤時」)。這樣可以釋放資料庫資源,並更容易發現「有問題」的執行。

既然你提到 HTTP 節點有 imageUrls,請檢查那些 URL 是否傳回大量的中繼資料,或回應本體是否出乎意料地龐大。即使不是影像本身,龐大的 JSON 回應也會導致記憶體飆升。

我剛檢查了執行失敗的情況,那是預設儲存。JSON 資料只包含圖片 URL,沒有其他類型的內容。我也查看了所有節點從 webhook 接收的資料(是的,該程式碼節點正在處理該資料)。這是一個基本的 Slack 事件 webhook,接收 20-30 行 API 請求中繼資料(在標頭中)和 10 行正文以及 JSON 中的一些其他資訊。(似乎沒有什麼問題)。我的問題是,如果我什麼時候去休假而這種情況發生,那麼系統可能會停機一段時間。

兩種可能性:

  1. 累積洩漏: 在 3 個月內,小量的記憶體可能沒有被正確清除。最終,「基線」記憶體使用量變得太高,以至於即使是很小的 Slack webhook 也會將其推過限制。
  2. 並行性: 如果 5 或 10 個 Slack 事件在同一秒內擊中你的 webhook,n8n 會啟動多個並行執行。即使每個都很小,10 個同時進程也會造成 RAM 尖峰並觸發當機。

由於你擔心系統在你休假時宕機,你不能依賴 n8n 自我監控(因為如果它當機,監控器也會當機)。你需要外部監控

使用免費服務,如 Better StackUptimeRobotCronitor

  • 在 n8n 中建立一個非常簡單的第二個工作流:Webhook 觸發器回應 Webhook (200 OK)
  • 設定外部監控每 5 或 10 分鐘 ping 一次此 URL。
  • 如果監控器收到 500 錯誤或逾時,它會立即傳送給你電子郵件/簡訊。你將在主要工作流遺失關鍵資料之前知道實例已宕機。

查看你的設定螢幕截圖,你的**「儲存成功的生產執行」設為「儲存」**。

  • 將其更改為「不儲存」。
  • 為什麼? 每次儲存成功的執行時,n8n 必須在記憶體中保存該資料並將其寫入磁碟。對於高頻率的 Slack webhook,這會在記憶體中造成持續的「磨損」。透過僅儲存失敗,你可以顯著減少實例上的負載。

由於你的資料客觀上很小,且你已經運行了 3 個月,這可能是你的實例所在的特定「節點」(物理伺服器)的問題。

  • 將「中斷」執行的螢幕截圖傳送給 n8n 雲支援或 help@n8n.io
  • 告訴他們:「我的工作流正在處理非常小的 Slack 承載,但我看到『中斷』執行,而且斷路器正在取消發佈我的流。你能檢查我的實例是否正在經歷記憶體壓力,或者我是否應該被移動到不同的主機嗎?」

我能做些什麼來修復累積洩漏嗎?比如重新啟動工作流程之類的?對我來說關閉成功的反覆運算可能不是一個選項(公司的實例,因此至少需要保留過去幾天的完整記錄。)並行可能是一個問題,因為所有3次失敗的執行同時發生(但我見過n8n處理8-10個,有時甚至更多)。可能不需要外部監控,因為n8n本身會發送一條訊息到郵件,告訴我們他們已關閉它,我們會收到通知。(我的意思是誰會帶著辦公室筆記型電腦去度假呢 :face_with_tongue: )

重新啟動工作流程本身不會清除洩漏;重設點是執行中的執行個體或背景工作程序。在這種情況下,更尖銳的線索是三個失敗同時發生,而不是 Code 節點很耗費資源。

檢查一個視窗,不需要員工資料:三個 Slack webhook 執行是否在相同的幾秒內開始,當時是否有任何其他執行在執行中?如果是,下一個邊界是員工更新路徑之前的小型佇列/序列閘,因此 Slack 會被快速確認,但一次只處理一個更新工作。如果它們分散開來,將其視為 Cloud/執行時事件,並向支援人員提供三個執行 ID 加上自動停用時間戳。

可能是併發的問題。有辦法處理這些嗎?比如我們能否通過延遲同時到達的執行來避免衝突?

Yes, this will help

是的,但不要在繁重節點之後放置延遲。如果三個 Slack 事件已經啟動完整工作流程,Wait 節點只會同時保持三個執行中。

保持 Slack 進度很小:接收事件、確認事件,並僅將員工更新所需的事件 id/body 放在一個一次性閘門後面。然後根據時間表或佇列處理該第二部分。你仍然可以保留執行記錄;要減少的是員工更新分支中的平行工作,而不是記錄保留本身。

我想事件本身已經很小了,因為 webhook 數據並不大(最多 50-60 行 json),而且我們只需要其中的幾個欄位(代碼節點正在執行的操作 — 數據的降維)。只是剛好請求是並行進來的。我見過 https 請求接收 MB 級別的數據仍然沒有崩潰。無論如何,我會盡力將這個問題提交給 n8n 團隊(如果我有辦法的話)。感謝幫助,今後會嘗試在工作流中實施這些建議。