指南

如何在網頁應用程式中運行背景工作:佇列、排程器與 Cron

要在網頁應用程式中運行背景工作,首先要把工作分為兩類。觸發式工作(發送歡迎電郵、處理上載的檔案)可以儲存到工作佇列中,通常就是資料庫中的一張資料表,然後由具備重試功能的工作程序處理。排程工作(每晚的報告、每 15 分鐘一次的提醒)則需要按時間表觸發的機制:由主機的 cron 功能提供,或由外部排程器呼叫應用程式中受保護的端點。務必讓工作可以安全地重複執行,記錄失敗的情況,並且不要依賴一個可能休眠或重新啟動的伺服器內的計時器。

本指南會講解各種選項、它們各自適用的情況,以及如何借助 AI 應用程式建置工具設定,包括在可以縮減至零的主機上的做法。

什麼算是背景工作

任何緩慢、不可靠,或不需要即時回應給用戶的工作:

  • 發送電郵、通知及收據
  • 調整圖片大小、轉碼影片、生成 PDF
  • 呼叫緩慢的第三方 API,包括為較長的任務呼叫 AI 模型
  • 從其他系統匯入或同步資料
  • 每晚的清理、報告及提醒

如果把這些工作放在請求之內進行,頁面會變慢,而且容易出錯:假如電郵服務供應商出現故障,用戶的註冊就會失敗。把它們移到背景執行,用戶可以立即獲得回應,而工作失敗時也可以重試。

各種選項

選項運作方式優點缺點
同一程序內「發射後不管」先回應,然後在伺服器中繼續處理不需要設定伺服器停止時會遺失;沒有重試
程序內計時器(setInterval、setTimeout)在運行中的伺服器內設一個計時器非常簡單休眠時不會執行;多個副本時會重複
資料庫佇列工作以資料列形式儲存;工作程序認領並執行使用你現有的資料庫;持久可靠;容易查看你需要自行建置重試與鎖定機制;需要有東西來運行工作程序
專用佇列(基於 Redis 或託管服務)佇列服務加上工作程序重試與排程功能成熟需要另外運行及付費的服務
託管的工作或工作流程服務第三方服務按步驟呼叫你的端點,並提供重試及排程排程和重試由服務代為處理依賴供應商;需要另一個帳戶及金鑰
外部排程器呼叫端點其他地方的計時器按時發送 HTTP 請求適用於任何託管平台,包括可縮減至零的平台有最短間隔及延遲;需要保護端點
主機內建的 cron平台按時間表運行指令在支援的地方非常簡單並非每個主機都提供

沒有單一的正確答案。小型應用程式通常只需要一個資料庫佇列,再加上一個外部排程器。

為何可縮減至零的主機會改變情況

許多現代的主機在沒有人使用應用程式時會讓它休眠,並在下次收到請求時喚醒。這樣可以節省費用,但休眠中的伺服器不會運行任何程式碼:計時器不會觸發,工作程序也不會輪詢。在這類主機上,排程工作必須由一個進入的請求開始,而最簡單的請求來源就是外部排程器。每次呼叫都會喚醒應用程式(通常連同其資料庫),因此每分鐘呼叫一次的成本,會高於每 15 分鐘呼叫一次。請選擇能夠滿足需要的最長間隔。

模式一:資料庫工作佇列

適用於觸發式工作:

  1. 建立一張 jobs 資料表,包含:類型、承載內容(JSON)、狀態(pending、running、done、failed)、嘗試次數、run_after、last_error 及時間戳記。
  2. 當某件事情發生時,在引發該變動的同一個交易中插入一筆工作資料列,這樣兩者會一同成功或一同失敗。
  3. 工作程序選取到期的工作,將其標記為 running,執行工作後再標記為 done。
  4. 如果失敗,增加 attempts,把 run_after 設定在較後的時間(例如 1、5、30 分鐘後),並儲存錯誤。達到最大次數後,將其標記為 failed,並通知相關人員。

如果有多個工作程序可能同時運行,工作必須以安全的方式被認領。在 Postgres 中,SELECT ... FOR UPDATE SKIP LOCKED 讓每個工作程序認領不同的資料列,而不會互相衝突。

那麼由什麼來運行工作程序呢?在一直運行的伺服器上,可以是獨立程序中的循環。在可以縮減至零的主機上,模式二中排程的端點,可以在每次呼叫時處理一批到期的工作。

模式二:由外部排程器呼叫你的應用程式

適用於排程工作:

  1. 新增一個端點,例如 POST /api/cron/send-reminders。
  2. 保護它:要求在標頭中附上一個機密權杖,並在雙方都將它儲存為機密;拒絕其他任何請求。
  3. 令它具備冪等性:在同一分鐘內執行兩次,不可以發出兩次提醒。記錄已發送的內容。
  4. 讓每次呼叫都簡短:處理一批(例如 100 項),餘下的交由下一次呼叫處理。
  5. 將排程器指向這個端點。

排程器的選擇:

  • GitHub Actions 排定工作流程。 在 GitHub 的使用限額內免費。根據 GitHub 於 2026 年 9 月的文件,最短間隔為每 5 分鐘一次;在繁忙時段(尤其是每小時開始時)執行可能會延遲;排程預設使用 UTC;而公開儲存庫中的排定工作流程,若超過 60 天沒有儲存庫活動,便會被停用。
  • 託管的 cron 服務。 有很多服務的唯一功能,就是按時間表呼叫一個網址。在依賴它們之前,請檢查其可靠性、最短間隔及警示功能。
  • 你的雲端服務供應商的排程器。 如果你已經使用大型雲端服務供應商,它通常會提供可以呼叫 HTTPS 端點的託管排程器。
  • 託管的工作或工作流程服務。 這些服務結合了排程、佇列及重試,並為每個步驟呼叫你的端點。請在各供應商的網站上比較價格及限制。

模式三:交由服務供應商處理

有時候最好的背景工作,根本就不需要自己做:

  • 付款。 Stripe 會為失敗的訂閱付款重試,並發送 Webhook;你只需回應,而不必輪詢。參閱什麼是 Webhook。
  • 電郵。 當你把郵件交給服務供應商後,供應商會排隊並重試傳送。
  • 大量 AI 工作。 OpenAI 及 Anthropic 為不急切的請求提供批次 API,你可以提交請求,之後再收取結果。

給 AI 建置工具的提示

用於佇列:

在我們的資料庫中加入一個背景工作佇列,使用 jobs 資料表(類型、承載內容 JSON、狀態、嘗試次數、run_after、last_error)。當用戶註冊時,在同一個交易中插入一個 send_welcome_email 工作,而不是直接在請求中發送。新增 processJobs(limit) 函式,使用 SELECT ... FOR UPDATE SKIP LOCKED 認領到期的工作並執行;失敗時在 1、5、30 分鐘後重試,嘗試 4 次後標記為 failed。

用於排程觸發:

新增 POST /api/cron/tick,以機密 CRON_SECRET 作為 bearer 權杖保護;拒絕任何沒有該權杖的請求。每次呼叫執行 processJobs(100),並發送未來 24 小時內到期、且尚未發送的預約提醒,同時記錄已發送的提醒,確保不會重複發送。以 JSON 摘要回傳執行的內容。然後撰寫一個 GitHub Actions 工作流程,每 15 分鐘呼叫這個端點一次,並從儲存庫的機密中讀取網址及權杖。

常見錯誤

  • 依賴 setInterval。 伺服器休眠或重新啟動時它會悄悄停止,而兩個副本同時運行時則會重複執行。
  • 未受保護的 cron 端點。 任何找到它的人都可以觸發你的工作,或令你的電郵費用上升。
  • 非冪等的工作。 重試及重複的排程器呼叫一定會發生。設計時就要把它們考慮在內。
  • 無法得知失敗情況。 一項工作在一星期內靜默地失敗,比大聲地失敗更糟糕。記錄錯誤,並在重複失敗時發出警示。
  • 在單一請求中進行長時間的工作。 請求會逾時。應分批處理。
  • 排程過於頻密。 在可縮減至零的主機上,每次呼叫都會喚醒並計費應用程式。間隔應配合實際需要。
  • 時區。 「早上 9 時」對你的排程器(通常是 UTC)與對你的用戶,意思可能不同。應以 UTC 儲存時間,並按用戶換算。
  • 把機密放在工作流程檔案中。 權杖應保存在排程器的機密儲存中。參閱如何妥善保管 API 金鑰。

檢查清單

  • 慢速的工作已移出用戶請求
  • 工作以持久方式儲存,而不只是存在記憶體中
  • 重試時間間隔逐步增加,並設有最大次數
  • 每項工作都可以安全地重複執行
  • 排程端點以機密權杖保護
  • 每次執行只處理有限的一批
  • 失敗的工作清晰可見,並設有警示
  • 排程間隔的選擇已考慮託管成本
  • 時間以 UTC 儲存

Mythex 的背景工作

Mythex 的文件並未描述排程或 cron 工作,而已發佈的應用程式及其資料庫在閒置時會休眠,並在下次請求時醒來(參閱託管限制)。因此,不要依賴應用程式內的計時器。可行的做法就是上面所述的方法:請 agent 建立一張 jobs 資料表和一個以權杖保護的端點,然後把外部排程器指向你已發佈的網址。把權杖儲存為專案機密,並留意每次喚醒都會為應用程式及資料庫醒着的時間消耗點數,因此請選擇合理的間隔。如果你的應用程式需要為此提供 API 後端,REST API 後端 食譜是一個起點;如何建立 REST API 則說明如何設計端點。如果你的產品核心是常駐的工作程序或機械人,一個專為持續運行的程序而設計的主機可能更適合你。

常見問題

什麼是背景工作?

背景工作是指應用程式在用戶等待的請求以外進行的工作,例如發送電郵、調整圖片大小、生成報告或同步資料。用戶可以即時獲得回應,而工作則會另外執行,失敗時還可以重試。

如果託管平台沒有 cron,我怎樣運行排程任務?

新增一個受保護的端點來執行工作,然後讓外部排程器按時間表呼叫它。可選的方案包括排定的 GitHub Actions 工作流程、託管的 cron 服務,或你的雲端服務供應商提供的排程器。請以機密權杖保護該端點。

我可以用 setInterval 或 setTimeout 執行排程工作嗎?

只適用於不重要的小型任務,而且伺服器必須一直運行。如果伺服器重新啟動、縮減至零,或同時運行多個副本,計時器就會遺失,或重複執行。排程的工作應儲存在資料庫中,或改用排程器。

Mythex 支援 cron 工作嗎?

Mythex 的文件並未描述排程或 cron 工作,而已發佈的應用程式在閒置時會休眠。較可靠的做法是讓外部排程器呼叫應用程式中受保護的端點,這會喚醒應用程式並執行工作。

Mythex · Pricing · 用 AI 建造任何嘢 · 網站及應用程式範本 · Mythex 比較 · AI 應用程式開發詞彙表 · 免費 AI 應用程式開發工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(台灣)