429 請求過多:這意味著什麼以及如何處理

當應用程式在一段時間內發送的請求超過 API 在該時段內允許的請求數量時,API 會回傳 429 Too Many Requests 。 這個請求本身沒問題。 你發送太頻繁,API 就拒絕了。 如果你等著再寄一次,通常會成功。 回覆通常會附上 Retry-After 標頭,告訴你該等多久。 欲了解更多資訊,請參閱 RFC 6585,第4節。

每個 API 對速率限制的實作方式都不同。 狀態碼、標頭和錯誤主體都會有所不同,因此正確處理一個 API 的程式碼可能會錯誤處理下一個。

API Status 如何判斷等待多久 小心
GitHub 403 或 429 retry-after 若存在,否則 x-ratelimit-reset(UTC 紀元秒數),當 x-ratelimit-remaining 為 0 時,否則至少 1 分鐘 403 可以是速率限制或缺少的權限。 看標題就能分辨兩者。
OpenAI 429 retry-after 有些 429 錯誤,比如 credit_balance_exhausted,代表重試不會有幫助。 檢查 error.code。
人為 429 retry-after 因支出上限而發生的 429 錯誤沒有 retry-after,且會持續失敗,直到存取恢復為止。 負載過高的 API 會回傳 529,而不是 429。
Microsoft Graph 429 Retry-After (秒) 限制因服務而異,例如 SharePoint 和 Outlook。

如何處理 429 錯誤

  1. 決定是否要重試。 如果錯誤顯示你的配額、信用點數或消費上限已用盡,重試也沒用。 告訴使用者,並向自己發出警示。
  2. 依 API 要求等待相應時間。 如果回覆中有 Retry-After,就等那麼久。 它要麼是秒數,要麼是 HTTP 日期。 如果 API 使用速率限制標頭,就像 GitHub 的x-ratelimit-reset那樣,請等到重置時間。
  3. 否則,請退後。 沒有 API 提示時,再用指數退縮和隨機抖動重試,嘗試幾次後停止。
  4. 告訴使用者發生了什麼事。 「系統忙碌,5秒後重試」比永無止境的旋轉機好。
  5. 在下一次 429 錯誤之前放慢請求速度。 如果 API 會傳送速率限制標頭,剩下的計數就用來調整請求的節奏。
async function fetchWithRetry(url, options, attempts = 3) {
  for (let attempt = 1; ; attempt++) {
    const response = await fetch(url, options);
    if (response.status !== 429 || attempt === attempts) {
      return response;
    }
    const retryAfter = response.headers.get('retry-after');
    const waitMs = retryAfter
      ? (isNaN(retryAfter) ? new Date(retryAfter) - Date.now() : retryAfter * 1000)
      : 2 ** attempt * 1000 + Math.random() * 1000;
    await new Promise(resolve => setTimeout(resolve, Math.max(waitMs, 0)));
  }
}

很多 SDK 會幫你重試 429。 例如,OpenAI Python SDK 預設會重試兩次,而 .NET 標準韌性處理器則重試三次並遵循 Retry-After。 當 SDK 用盡重試次數時,你的程式碼會收到錯誤,因此仍然需要因應方案。

如何測試你的應用程式是否能處理 429

在開發過程中,你很少會看到429。 API 很快,你是唯一的使用者,測試資料也很小。 所以你測試 429 處理的方式,決定了你是否比使用者先發現錯誤。

Approach 你發現的 你錯過的內容
等待正式環境 實際故障 在使用者點擊之前的一切
在測試中模擬 API,或讓你的編碼代理寫出模擬 不管你的重試分支是否執行 API 的真實狀態碼、標頭和錯誤內容,以及你的 SDK 重試政策。 你的應用程式也需要一個只供測試使用的開關來連到模擬服務。
呼叫真正的 API,直到它對你進行速率限制 實際行為 你無法隨時觸發429,而且你的真實配額會用掉
攔截你應用程式的真實流量,並按需回傳 429 回應 真實網址、真實的 SDK 與重試政策,以及 API 自有的 429 格式 你的應用程式裡沒有任何變化,所以它不會在隔離的環境中測試你的程式碼。 把那個留給你的單元測試處理。

在你的應用程式中試試看

Dev Proxy 會攔截你應用程式對你選擇的 API 的請求,並回傳 429,附帶 API 自己的標頭和錯誤格式,而你的應用程式則持續呼叫真實的 URL。 它還會告訴你,您的應用程式何時會在 Retry-After 時間結束前重試。

下載你應用程式呼叫的 API 預設集,並用它啟動 Dev Proxy:

devproxy config get github-rate-limiting
devproxy --config-file "~dataFolder/configs/github-rate-limiting/.devproxy/devproxyrc.json"
API Preset
GitHub github-rate-limiting
OpenAI openai-throttling
Anthropic anthropic-throttling
Microsoft Graph(OneDrive 與 SharePoint:/drive, /shares, /sites) microsoft-graph-rate-limiting

然後照常執行你的應用程式,觀察它的表現。 要安裝 Dev Proxy,請參見 設定 Dev Proxy。

下一步

也請參閱