Retry-After は、次の要求を送信するまでの待機時間をアプリに伝える HTTP 応答ヘッダーです。 値は秒数または HTTP 日付です。 API から送信された場合は、リクエストを拒否したサーバーから送信されるため、「いつ再試行できるか」に対する最も信頼性の高い回答になります。 詳細については、 RFC 9110 セクション 10.2.3 を参照してください。
Retry-After の見え方
ヘッダーには 2 つの形式があります。 アプリで両方を処理する必要があります。
| Format | Example | 意味 |
|---|---|---|
| Seconds | Retry-After: 120 |
応答を取得してから 120 秒 (2 分) 待ちます。 値は非負の整数です。 |
| HTTP 日付 | Retry-After: Fri, 31 Dec 1999 23:59:59 GMT |
この時刻より前にリクエストを再度送信しないでください。 日付は常に GMT です。 |
サーバーは、これらの状態コードで Retry-After を送信します。
| Status |
Retry-Afterの意味 |
Source |
|---|---|---|
429 Too Many Requests |
新しい要求を送信するまでの待機時間。 サーバーにそれが含まれる場合があります。 | RFC 6585、セクション 4 |
503 Service Unavailable |
サービスが利用できないと見込まれる期間。 サーバーがそれを含む場合があります。 | RFC 9110、セクション 15.6.4 |
413 Content Too Large |
条件が一時的な場合、サーバーは、どのくらいで解消されるかを示す必要があります。 | RFC 9110、セクション 15.5.14 |
任意の 3xx リダイレクト |
リダイレクトに従う前に待機する最小時間。 | RFC 9110、セクション 10.2.3 |
ヘッダーは省略可能です。 一部の API では、代わりに独自のヘッダーが使用されます。 たとえば、GitHubは、制限がいつリセットされるかをx-ratelimit-resetで知らせてくれます。 詳細については、GitHub API のレート制限を超えましたを参照してください。
Retry-After を処理する方法
- 両方の形式を読みます。 値が数値の場合は秒です。 それ以外の場合は、日付として解析し、現在の時刻を減算します。 日付が既に過去の場合は、すぐに再試行できます。
- ヘッダーに表示された時間以上待ってください。 早めに再試行すると、通常、別の
429または503が返されます。 一部の API では、スロットリングされている間も要求がカウントされ続けるので、早期の再試行によって待機時間が長くなる可能性があります。 たとえば、Microsoft Graph のスロットリングに関するガイダンスを参照してください。 - ヘッダーが見つからない場合は、ジッター付きバックオフにフォールバックします。 試行が失敗するたびに待機を 2 倍にし、多数のクライアントが同時に再試行しないようにランダムな量を追加し、待機を上限にします。
- 再試行回数を制限してください。 数回試行した後、エラーを呼び出し元に返します。
- 再試行が役に立つかどうかを確認します。 一部の API は、クレジットや使用制限が使い切ったときに
429を返します。 待っていても解決しません。 例については、「 OpenAI のinsufficient_quotaとcredit_balance_exhausted」を参照してください。
function retryDelayMs(response, attempt) {
const value = response.headers.get('retry-after');
if (value) {
const seconds = Number(value);
const ms = Number.isNaN(seconds) ? Date.parse(value) - Date.now() : seconds * 1000;
if (!Number.isNaN(ms)) {
return Math.max(ms, 0);
}
}
// No usable header: exponential backoff with jitter, capped at 30 seconds
return Math.random() * Math.min(30_000, 1_000 * 2 ** attempt);
}
人気のある SDK でできること
多くの SDK は Retry-After を処理しますが、再試行回数を使い切るまでしか処理しません。 すると、コードでエラーが発生します。
| SDK | 既定での動作 |
|---|---|
| .NET 標準回復性ハンドラー | 指数バックオフとジッターを使用して、 408、 429、および 5xx 応答を最大 3 回再試行します。
true は既定で Retry-After になるため、遅延には ShouldRetryAfterHeader が使用されます。 |
| Microsoft Graph SDKs |
Retry-Afterが存在する場合は使用し、存在しない場合は指数バックオフにフォールバックします。 JSON バッチ内の要求は自動的には再試行されません。 |
| OpenAI Python SDK | 接続エラーと 408、 409、 429、および 5xx 応答を短い指数バックオフで 2 回再試行します。
max_retriesを設定して変更します。 |
SDK のドキュメントで正確なポリシーを確認し、最後の再試行が失敗した後に何が起こるかをテストしてください。
アプリが Retry-After を処理することをテストする方法
開発中に Retry-After を取得することはほとんどなく、その値を制御することはできません。 そのため、これをテストする方法によって、ユーザーより先にバグを見つけられるかどうかが決まります。
| Approach | 見つけたもの | 見逃したもの |
|---|---|---|
| 本番環境を待機 | 実際の障害 | ユーザーがそれをクリックするまでのすべて |
| テストで API をモックするか、コーディング エージェントにモックを記述させる | コードがヘッダーを解析するかどうか | 実際の HTTP クライアントまたは SDK が十分に長く待機しているかどうか、および API が実際に何を送信するか。 アプリでは、モックに到達するためにテスト専用のスイッチも必要です。 |
| レート制限されるまで実際の API を呼び出す | 実際の動作 | オンデマンドでスロットリングされた応答をトリガーすることはできません。実際のクォータを消費してしまいます |
| アプリの実際のトラフィックをインターセプトし、オンデマンドでスロットルされた応答を返す | 実際の SDK と再試行ポリシーがヘッダーが示す時間どおりに待機するかどうか | アプリ内では何も変更されないため、コードを独立した状態でテストするわけではありません。 そのための単体テストは取っておいてください。 |
アプリで試す
Dev Proxyは、選択した API に対するアプリの要求をインターセプトし、Retry-After応答を 429 ヘッダーとともに返しますが、アプリは実際の URL を呼び出し続けます。
RetryAfterPlugin は、スロットリングされた各リクエストが再試行されるタイミングを記憶します。 アプリがその時刻より前に同じ URL を呼び出した場合、Dev Proxy はそれを報告し、要求を再度スロットルします。 プラグインは 429 応答のみを追跡します。
GenericRandomErrorPlugin のエラー ファイルで、Retry-After 応答の 429 値を @dynamic に設定すると、Dev Proxy で秒数が自動的に入力され、追跡されます。
これを試すには、両方のプラグインを使用するプリセットをダウンロードし、それを使用して Dev Proxy を起動します。
devproxy config get openai-throttling
devproxy --config-file "~dataFolder/configs/openai-throttling/.devproxy/devproxyrc.json"
その後、通常どおりにアプリを実行し、どのように動作するかを確認します。 Dev Proxy をインストールするには、「Dev Proxy のセットアップ」を参照してください。
次のステップ
参照
Dev Proxy