我正在使用 HTTP Request 節點呼叫外部 API。該 API 有時回應較慢,所以我啟用了重試選項。問題是某些請求最終在外部系統中建立重複記錄。
描述問題/錯誤/問題
從執行歷史來看,即使第一個請求可能已到達 API,該請求仍會被重試。有沒有辦法在不完全停用重試的情況下防止這種情況
錯誤訊息是什麼(如果有的話)?
請分享您的工作流程
(在畫布上選擇節點,並使用鍵盤快捷鍵 CMD+C/CTRL+C 和 CMD+V/CTRL+V 來複製和貼上工作流程。)
分享最後一個節點傳回的輸出
關於您的 n8n 設定的資訊
- n8n 版本:1.123.x
- 資料庫(預設:SQLite):
- n8n EXECUTIONS_PROCESS 設定(預設:own、main):
- 透過以下方式執行 n8n(Docker、npm、n8n cloud、桌面應用程式):
- 作業系統:
嘿 @Amidu_Louis 歡迎加入社群!是的,你可以保留重試。重複項來自「失敗時重試」的運作方式:它會重新運行整個節點,而不僅僅是失敗的請求。HTTP 請求節點會發送它收到的每個項目,如果其中一個出錯,節點就會失敗,重試會再次發送所有項目,包括已經建立記錄的項目。
將 HTTP 請求放在「批次大小為 1 的逐項循環」內,這樣節點的每次運行都只處理一個項目,重試只會重新發送那個項目。如果 API 支持冪等性密鑰(Stripe 稱之為 Idempotency-Key 標頭),也請發送一個在重試時保持相同的密鑰,例如來自你自己數據的 ID,這樣超時後到達 API 的請求就不會建立第二條記錄。
也值得檢查節點上的「選項 > 逾時」。添加該選項後,它預設為 10 秒,所以較慢的響應會被視為失敗並重試。
單項迴圈只有在多個輸入項目到達 HTTP Request 節點且重試正在重放成功的同級項時才有幫助。它不能解決你的問題中的逾時情況:相同的請求可能已在回應遺失前建立了記錄
我會先檢查目的地是否接受穩定的冪等性金鑰。如果不接受,請保留業務衍生的操作參考,並在重試模稜兩可的結果前與目的地進行協調。僅本地「已見」標旗無法證明遠端寫入失敗
關於「迴圈遍歷項目 + 冪等性」建議,還有一點要補充:對於非冪等的 POST,我根本不會使用 HTTP Request 節點內建的「失敗時重試」功能。它無法區分逾時(此時請求可能已建立記錄)和完全失敗的情況。
相反地,將該節點設定為「錯誤時 > 繼續」(使用錯誤輸出),並自行建構重試邏輯:如果狀態是 429,或是在傳送前連線就失敗了,等待幾秒鐘後重試一、兩次。如果是逾時,先用你自己為該記錄設定的唯一參考進行 GET 查詢,只有在找不到該記錄時才重新 POST。將逾時視為未知情況,而非失敗。提高節點中的「選項 > 逾時」設定會有幫助,但無法消除這種歧義。
嗨 @Amidu_Louis,希望你一切安好
這可能發生在 API 處理請求但 n8n 未能及時收到回應的情況。重試機制隨後會發送相同的請求。如果 API 支援冪等性金鑰,請為每個操作使用唯一的金鑰,這樣重複的請求就不會建立重複的記錄。如果不支援,你需要在建立記錄前先檢查該記錄是否已存在
重試機制很有用,但對於建立資料的 POST 請求,它們本身並不總是安全的
補充 Deepankar 的回答:提高逾時後,開啟其中一個重複的執行,查看第一次嘗試的錯誤。如果它是逾時/ECONNABORTED 而不是 5xx,該請求可能已到達 API,盲目重試將始終存在重複的風險。在這種情況下,關閉「失敗時重試」,將「錯誤時」設為「繼續(使用錯誤輸出)」,只在請求顯然從未到達的錯誤時迴圈(429、ECONNREFUSED)。小提示:標題提到了代碼節點,所以編輯它將幫助其他人找到此答案。
@Amidu_Louis,查詢後重試的建議中有一個邊界情況:逾時後立即進行的空 GET 並不能證明原始 POST 失敗。第一次寫入可能仍在處理中,或查詢可能滯後於該寫入。然後重試 POST 可能會產生重複。
沙箱/模擬 API 中的實用測試:
- 傳送操作
order-123,並延遲其提交直到用戶端逾時之後。
- 讓立即查詢不返回任何記錄。
- 在第一次寫入仍在進行時重試。
- 讓兩者都完成並計算
order-123 的記錄數。
驗收檢查是一條遠端記錄,包括在重新啟動的工作流程中。在提供商支持的情況下,在提供商記錄保留期間內為該邏輯操作保留並重複使用相同的冪等性金鑰。重試時使用新金鑰會破壞保護。如果 API 提供此功能,伺服器強制執行的唯一業務參考/原子 upsert 也可以幫助。
沒有任何一種保證的情況下,將逾時視為未知結果:使用有限的等待進行協調,然後將未解決的情況路由進行審查,而不是盲目地再次建立。更長的逾時或批次大小 1 可以減少某些失敗,但無法保證單次遠端寫入。
Hi @Amidu_Louis,
我是 Zara,來自 n8n 支援團隊。歡迎加入社群!
基於 @Deepankar、@Mahdi_Eqbal 和 @heroxcreed 已經說過的內容:重複出現是因為「失敗時重試」無法區分逾時和真正的失敗。如果 API 建立了記錄但回應遲到,n8n 會偵測到錯誤並重新發送同一個 POST。重試也會重新執行整個節點,所以如果有多個項目進入而其中一個失敗,已經成功的項目也會被重新發送。
將 HTTP Request 放在「Loop Over Items」內並設定「Batch Size 1」可以解決第二種情況,但如 Mahdi 所指出的,這對逾時沒有幫助。對於逾時,最佳的解決方案是使用冪等金鑰(如果 API 支援的話),使用在重試時保持不變的值,例如來自您自己資料的 ID(不是在節點內產生的隨機值)。如果不支援,請遵循 heroxcreed 的方法:關閉該節點的內建重試,將「錯誤時」設定為「繼續」(使用錯誤輸出),逾時時先根據您自己的唯一參考做 GET 查詢,然後再重新 POST。將逾時視為「未知」,而不是「失敗」。
另外檢查「選項 > 逾時」,因為新增後預設為 10 秒,所以緩慢的回應可能會自動觸發重試。
如果您仍然遇到問題或有任何疑惑,請隨時寫信至 help@n8n.io,我們的團隊會確保協助您。