第4章 信頼性とエラー処理
学習目標
- ステータスコード、本文のエラーコード、ヘッダーからエラーを読み、リトライするもの、修正するもの、人が判断するものに分ける。
- レート制限の構造と429のさまざまな原因を説明し、トラフィックを調整する。
- ジッターと予算を備えるリトライ方針を1つの層に設計し、層別のタイムアウトと期限を決める。
- 冪等キーで副作用のある操作を安全に繰り返し、結果不明の状態から復旧する。
- 中断された応答と部分的な失敗から復旧し、障害がほかの機能へ広がるのを防ぐ。
はじめに
午前2時、原稿の校正処理が止まりました。担当者は朝の出勤後、最初からやり直しました。昼ごろ、編集者から同じ章の校正結果が2つずつあると連絡が来ました。ログを見ると夜間に529と429が混在し、リトライのロジックはすべての失敗を1秒間隔で無限に繰り返していました。障害への対応が、障害自体より大きな被害を生んだのです。
外部APIを使うシステムで、失敗は例外ではなく日常です。大切なのは失敗の種類を区別し、種類ごとの対応を行い、同じ仕事を二重に実行しないことです。本章は、エラー分類、レート制限、リトライとバックオフ、タイムアウト、冪等性、中断された応答と部分的な失敗、障害の隔離の順に進めます。
重要な概念
成功、失敗、そして結果不明
リクエストの結果は2つではなく3つです。成功の応答を受け取った場合、失敗の応答を受け取った場合、あるいは応答を何も受け取れなかった場合です。3つ目を結果不明と呼びます。接続が切れる前にサーバーが処理を完了していたかもしれませんし、まだ始めていなかったかもしれません。
モデル呼び出し自体は、結果不明でも送り直せば済みます。少しコストが増えるだけで、外の世界は変わりません。問題は、副作用のある操作です。返金、予約作成、メール送信が結果不明の場合、「失敗」とみなして再実行した瞬間に二重実行になり得ます。結果不明の変更操作は、次の順で扱います。
- 同じ業務キーで実際の状態を照会する。
- すでに反映されていれば、その結果を成功として使う。
- 未反映と確認できれば、同じ冪等キーで再実行する。
- 照会できなければ自動で再実行せず、保留にして人に知らせる。
エラーの分類表
ベンダーごとに名前は違いますが、ステータスコードの意味は似ています。
| ステータス | Anthropic | OpenAI | Gemini(Interactions API) | 対応 |
|---|---|---|---|---|
| 400 | invalid_request_error(自分で設定した支出上限への到達を含む) |
不正なリクエスト | invalid_request、failed_precondition |
リクエストか設定を修正 |
| 401 | authentication_error |
認証エラー | — | キーの確認・交換 |
| 402 | billing_error |
— | payment_required |
決済情報に対応。リトライしない |
| 403 | permission_error |
非対応の地域など | permission_denied |
権限・アクセス設定を確認 |
| 409 | conflict_error |
競合 | — | 競合を解消してからリトライ |
| 413 | request_too_large(Messages APIは32MB) |
— | — | リクエストのサイズを減らす |
| 429 | rate_limit_error |
複数の原因(次節) | rate_limit_exceeded、too_many_requests、quota_exceeded |
原因によって異なる |
| 500 | api_error |
サーバーエラー | api_error |
バックオフ後にリトライ |
| 503 | — | server_is_overloaded |
service_unavailable |
バックオフ後にリトライ |
| 504 | timeout_error |
— | deadline_exceeded |
ストリーミング・バッチを検討し、クライアントの期限を確認 |
| 529 | overloaded_error |
— | — | バックオフ後にリトライ |
Geminiは400、402、403などのクライアントエラーはリトライしないよう明記し、OpenAIも、不正なリクエストは修正するまで同じ結果になると説明しています。
リトライすべきエラーを選ぶ決定表
ステータスコードだけでは不十分です。本文のエラーコードとヘッダーも読み、3つの問いに答えます。
| 問い | はい | いいえ |
|---|---|---|
| 同じリクエストが、時間がたてば成功する可能性があるか | レート制限、過負荷、一時的なサーバーエラー | 形式エラー、認証エラー、支出上限、決済の問題 |
| 繰り返しても安全か | モデル呼び出し、照会、冪等キーのある変更 | 冪等キーのない変更操作 |
| 待てる時間が残っているか | 期限まで余裕がある | ユーザーがすでに離れた、または期限が過ぎた |
3つとも「はい」の場合だけ、自動でリトライします。1つ目が「いいえ」ならリクエストを修正するか人に知らせ、2つ目なら結果不明の手順へ、3つ目なら失敗を確定して代替経路へ進めます。
レート制限の構造
レート制限は、一定時間に許されるリクエストとトークンの上限です。ベンダーごとに測る単位が違います。
| ベンダー | 単位 | 範囲 |
|---|---|---|
| Anthropic | モデルのグレード別の分間リクエスト(RPM)、分間入力トークン(ITPM)、分間出力トークン(OTPM) | 組織。ワークスペースごとに、より低い上限を設定可能 |
| OpenAI | RPM、RPD、TPM、TPD、分間画像数(IPM)など | 組織とプロジェクト。一部のモデル群は上限を共有 |
| Gemini | RPM、分間入力トークン(TPM)、日次リクエスト(RPD) | APIキーでなくプロジェクト。RPDは太平洋時間の午前0時にリセット |
Anthropicは、トークンバケットのアルゴリズムを使います。バケツに一定の速度で水が補充され、リクエストごとにすくい出す構造で、決まった時刻に一括リセットされません。そのため、分間60回の上限が秒間1回として適用されることがあり、分間総量が上限内でも、短時間に集中すると429になります。使用量の急増で加速制限(acceleration limit)に達することがあるため、トラフィックは徐々に増やすよう勧めています。
残りの上限は、応答ヘッダーでわかります。Anthropicはanthropic-ratelimit-requests-remaining、anthropic-ratelimit-input-tokens-remainingのように、項目別の上限・残量・リセット時刻を返します。OpenAIはx-ratelimit-remaining-requests、x-ratelimit-remaining-tokensなどを返します。計算方法の差も覚えておきます。OpenAIはmax_tokensと推定トークンの大きいほうでトークン上限を計算し、キャッシュ入力もTPMに数えます。AnthropicのOTPMは実際の生成量だけを数え、大半のモデルではキャッシュ読み取りをITPMに数えません。
429の読み方
同じ429でも、原因で対応は正反対になります。
| 原因 | 見分け方 | 対応 |
|---|---|---|
| 速度上限の超過 | 通常はretry-afterヘッダーがある(ない場合もある) |
少なくとも指定時間を待ってリトライ |
| 急激な増加 | Anthropicの加速制限、OpenAIのslow_down |
リトライしつつ、トラフィックの増加速度を落とす |
| Anthropicの利用ティア別支出上限 | retry-afterがなく、error.details.error_codeがenforced_spend_limit_reached |
リトライ停止。SDKの自動リトライも失敗する。担当者へ通知 |
| OpenAIのクレジット・支出・使用量上限 | クレジット枯渇や上限超過のエラーコード | リトライは無意味。クレジット追加か上限調整 |
| Geminiの日次クォータ | quota_exceeded |
リセットを待つか増枠申請 |
Anthropicで、組織やワークスペースに自分で設定した支出上限に達すると、429でなく400のinvalid_request_errorが来る点も覚えてください(Claude Codeのワークスペース上限は例外で、retry-after付き429です)。表のGeminiのコードはInteractions APIのもので、generateContent APIはRESOURCE_EXHAUSTEDなど別形式です。ステータスコードではなく、原因で分岐する必要があります。
指数バックオフとジッター
リトライするエラーなら、待ち時間を決めます。指数バックオフ(exponential backoff)は、試行のたびに待ち時間を2倍にします。ジッター(jitter)はランダムな揺らぎを加え、同じ障害に遭った多数のクライアントが同時に再集中するのを防ぎます。エレベーター前の列が崩れたとき、全員がきっかり10秒後に駆け戻れば再び混乱するのと同じです。
function backoffMs(attempt: number, retryAfterSec?: number): number | null {
const base = 500, cap = 30_000;
if (retryAfterSec !== undefined) {
const wait = retryAfterSec * 1000 + Math.random() * 1000; // 最小待ち時間+小さなランダム遅延
return wait > cap ? null : wait; // 上限を超えたらnull:リトライせず失敗を確定する
}
const ceiling = Math.min(cap, base * 2 ** attempt);
return Math.random() * ceiling; // フルジッター:0~上限から選ぶ
}
OpenAIは、Retry-Afterを最小待ち時間とし、小さなランダム遅延を加え、試行回数と総リトライ時間の両方に上限を設けるよう勧めています。失敗したリクエストも分間上限に含まれるため、送り続けると状況を悪化させるだけだとも警告しています。
リトライは1か所で、予算の範囲内で行います
リトライは複数の層に隠れています。Anthropicの公式SDKは、接続エラー、429、5xxを既定で2回、指数バックオフでリトライし、retry-afterに従います。max_retriesで変更できます。GeminiのPython SDKは一時的なエラーを最大4回、OpenAIの公式SDKは接続エラーと408・409・429・5xxを既定で2回リトライします。さらにアプリケーションのラッパー、ジョブキュー、APIゲートウェイが独自にリトライすると、回数は掛け算になります。
AWS Builders' Libraryは、リトライを「利己的」と表現します。自分のリクエストの成功率を上げるため、サーバーの容量を追加で使うからです。そのため、スタックの1か所だけで行い、依存サービスが健全に見えるときにだけリトライするよう勧めています。実践方法は次のとおりです。
- リトライを担当する層を1つ決めます。SDKに任せるならラッパー側を無効にし、ラッパーで行うならSDKのリトライを0にします。設定名はSDKと言語で異なります(例:Pythonの
max_retries、TypeScriptのmaxRetries)。 - リトライ予算を設けます。試行回数、総待ち時間、全リクエストに対するリトライ比率(例:10%)に上限を定めます。正常な応答ごとに少しトークンを補充し、リトライ時に消費するクライアント側のトークンバケットを設けると、障害時のリトライの急増を防げます。
- 元のリクエストIDと試行番号をログに残します。1件が実際に何回送られたかを把握して初めて予算を守れます。
タイムアウトを層別に設計します
1つのタイムアウトですべての待機を扱うと、早く切りすぎたり、長く保持しすぎたりします。3層に分けます。
| 層 | 意味 | 決め方 |
|---|---|---|
| 接続タイムアウト | TCP・TLS接続の確立まで | 短く、数秒 |
| アイドルタイムアウト | ストリームで次のイベントが来るまで | 正常な応答で観測したイベント間隔の高いパーセンタイル(p99など)に余裕を加えた値 |
| 全体の期限 | ユーザーに答えるべき絶対時刻 | 応答契約のレイテンシ目標 |
AWSは、下流サービスのレイテンシ分布から高いパーセンタイル(例:p99.9)を選び、誤検知によるタイムアウトを少ない割合で許容する方式を紹介しています。期限は下流へ伝播します。ツール実行時は残り時間を渡し、期限後に終わる処理は開始しません。
長い生成リクエストは、ストリーミングやバッチに送ります。Anthropicは、10分を超え得るリクエストにこれらを勧めています。一部のネットワークが、長時間アイドル状態の接続を切るためです。SDKは非ストリーミングのリクエストが10分を超えないかを検査し、TCP keep-aliveを設定します。OpenAI SDKの既定タイムアウトも10分です。OpenAIによると、同期の応答は接続を切ってキャンセルしますが、バックグラウンドモードなどサーバー上の処理は、明示的にキャンセルしなければ止まりません。中間層だけが接続を切り、アプリサーバーの上流リクエストが生きていれば、生成と課金は続きます。
冪等性:2回押しても1回だけ
エレベーターの呼び出しボタンは、何度押しても1台だけ来ます。同じリクエストを複数回送っても、1回送った場合と結果が同じ性質を冪等性と呼びます。HTTP標準(RFC 9110)は、PUT、DELETE、安全なメソッドを冪等と定めています。また、非冪等リクエストの自動リトライには、それが実際には冪等だとわかっているか、元のリクエストが適用されなかったと確認する手段が必要だとしています。AWSも、副作用のあるAPIは、冪等性を提供しない限り安全にリトライできないと整理しています。
アプリケーションで冪等性を作る方法は次のとおりです。
- 1つの操作に1つのキーを決め、その操作の全リトライで同じキーを使う。例:ツール呼び出しIDから作るキー、または
refund:{注文番号}:{返金回次}のような業務キー。 - 受信側はキーに一意制約を設け、状態(処理中、完了、失敗)、リクエスト内容のハッシュ値(フィンガープリント)、結果を保存する。同じキーが同時に来ても1件だけ処理するよう、キーの確保をアトミックに行う(例:一意制約を使った挿入)。
- 同じキーが再び来たら、保存済みの結果を返す。同じキーで内容が異なるなら、競合として拒否する。
- キーの保存期間は、リトライが起こり得る期間より長くする。
モデルが返すツール呼び出しIDは、呼び出しごとに一意で、キーの材料に適します。同じツール呼び出しをネットワークエラーで再送するとき、同じキーが付くので、受信側は重複を認識できます。リトライごとに新しいキーを作ると、この仕組みは崩れます。また、モデルへのリクエスト自体を再送し、モデルが同じ操作を新しい呼び出しで提案し得る流れなら、注文番号などの業務識別子もキーに入れ、受信側が同じ操作と認識できるようにします。受信イベントも同様です。OpenAIのWebフックはまれに同じイベントを2回送ることがあるため、webhook-idヘッダーで重複排除するよう案内しています。
中断された応答を復旧します
ストリーミングは、200応答の後でも失敗します。イベント単位でエラーを扱い、切断時の復旧方針を事前に決めます。
- Anthropic:受信部分を保存し、続きを要求できます。Claude 4.5以下では受信部分を新しいassistantメッセージの冒頭に入れ、Claude 4.6以降では受信部分と「途切れた箇所から続ける」というuserメッセージを送ります。ツール使用ブロックと思考ブロックは部分復旧できないため、最後のテキストブロックまでの続きだけを受け取り、残りは新たに要求します。続きには重複や不整合が起き得るので、構造化出力など形式が重要な結果は、最初から要求し直すほうが安全です。
- OpenAI:時間のかかる処理は
background: trueでサーバー上で実行し、状態をポーリングします。ストリーミングと併用する場合、各イベントのsequence_numberをカーソルとして保存し、切断後にstarting_afterでその位置から受信を再開できます。データ無保持(ZDR、zero data retention)プロジェクトではstore=falseで動き、レスポンスデータはポーリング用に約10分間、一時保存されます。
未完成の結果を見せることと、業務の完了を確定することは別です。途切れた応答のプレビューは「生成中」にし、完成して検証を通った結果だけを保存します。
部分的な失敗から復旧します
複数単位からなる処理では、一部だけ失敗することがよくあります。原則は「成功は保持し、失敗分だけ原因別にやり直す」です。
- 並列ツール呼び出し: 一部が失敗したらエラー結果を返し、モデルに次の行動を決めさせます。実行しなかった呼び出しにも、理由を含む結果を返します(第2章)。
- バッチ: 結果を成功、エラー、キャンセル、期限切れに分けます。期限切れ・キャンセル・サーバーエラーは再投入し、形式エラーは修正前に再投入しません。成功済みの項目は再生成しません。
- 多段階パイプライン: 項目ごとの状態(待機、進行、完了、失敗、隔離)を保存し、各段階の完了時にチェックポイントを残します。再起動時は完了済みをスキップします。
- 取り消せない操作: メール送信など取り消せない操作は、補償処理の手順(訂正メール、手動対応)を別途決めておきます。
同じエラーを繰り返す入力はデッドレターキュー(dead letter queue)へ移し、ほかの処理を妨げないようにして、人が原因を調べます。
障害が広がるのを防ぎます
外部APIが長く遅延・失敗すると、待機するスレッドや接続が蓄積し、無関係な機能も遅くなります。船の隔壁のように、被害を区画内に閉じ込める仕組みが必要です。
| 仕組み | 動作 | 設定するもの |
|---|---|---|
| キューへの受け入れ制限 | 待機リクエストが一定数を超えたら、新規を即座に拒否 | 最大待機数、拒否時のユーザー案内 |
| リソースの隔離(バルクヘッド) | 機能ごとに同時実行数と接続プールを分ける | 機能ごとの同時実行上限 |
| サーキットブレーカー | 失敗率が閾値を超えたら一定時間呼び出しを止め、その後一部だけ試して回復を確認 | 失敗率の閾値、遮断時間、試験リクエスト数 |
| 代替経路 | 事前評価済みの別モデル・ベンダー、機能縮小、静的な案内 | 品質基準、切り替え・復帰の条件 |
サーキットブレーカーの状態は3つです。電気回路と同じく、閉じていると電流が流れます。正常(閉)では呼び出しを通し、遮断(開)では即座に代替経路へ送り、試験(半開)で一部が成功すると再び閉じます。代替モデルを障害後に選ぶのでは遅すぎます。普段から同じ評価セットで品質を確認し、切り替えの事実をログと指標に残します。
さらに深く
リトライストームの分析
リトライは層ごとに掛け算になります。APIゲートウェイが1回、アプリケーションのラッパーが3回、SDKが既定で2回リトライすると、失敗が続くとき、ユーザーの1リクエストは最大(1+1)×(1+3)×(1+2)=24回APIに送られます。障害中に通常の数十倍のトラフィックが集中し、失敗も上限を消費するので、回復がさらに遅れます。バックオフがあっても、掛け算の構造は変わりません。
防ぐ順序は次のとおりです。第1に、リトライの層を1つにします。第2に、比率で予算を設けます。通常リクエストに対するリトライが一定比率を超えたら停止し、早く失敗を確定します。第3に、サーキットブレーカーにより、依存サービスが不健全ならリトライせず代替経路を使います。第4に、障害後にたまった処理を一気に放出しません。再び加速制限に達しないよう、処理量を段階的に増やします。
失敗を注入し、復旧方針を検証します
正常な応答だけでは、リトライや重複防止の欠陥は見つかりません。モデル呼び出しとツール呼び出しの前に偽の応答を挟む障害注入の層を作り、次を再現します。
| 注入する障害 | 確認すること |
|---|---|
retry-after付き429、ヘッダーのない一時的429、支出上限のエラーコード付き429 |
前2つはバックオフでリトライ、支出上限は即座に停止・通知 |
| 529・500の連続 | 予算内で回復するか代替経路へ進む |
| ストリームの途中切断 | 未完成の結果が保存されないか |
| 変更操作の成功直後に応答を失う | 結果不明の手順で照会し、二重実行がないか |
| バッチの一部失敗、同じWebフックを2回 | 成功済みを再生成せず、同じイベントを1回だけ処理するか |
検査基準は3つです。同じ業務が二重実行されないか、1リクエストの実際の送信回数が予算内か、最終状態の表示が実態と一致するかです。この試験をデプロイパイプラインに入れると、リトライの修正ごとに回帰を検出できます。
実務の場面
清らか泉浄水器:60秒で途切れるレポート
浄水器レンタル会社「清らか泉浄水器」の訪問技術者向けアプリは、点検前に顧客別の水質履歴レポートを生成します。レポートが長くなってから約15%のリクエストが失敗し、技術者が再試行ボタンを押して同じものを2、3回生成することが増えました。コストは生成されたレポート数に見合う額より40%多くなりました。
バックエンド担当のポンさんが確認すると、アプリサーバーは非ストリーミングでモデルを呼び、社内APIゲートウェイのリクエストタイムアウトは60秒でした。長いレポートは70~90秒かかり、ゲートウェイで切断されても、アプリサーバーのモデル呼び出しは生きていて最後まで生成・課金されていました。ゲートウェイ、アプリのラッパー、SDKが各自リトライもしていました。
ポンさんの修正は次のとおりです。
- レポート経路をストリーミングに変え、ゲートウェイでその経路のバッファリングを無効にする。タイムアウトは「イベント間のアイドル30秒」と「全体の期限4分」にする。
- リトライはSDKの1か所だけとし、ラッパーとゲートウェイでは無効にする。
- 技術者が画面を閉じたら、上流のストリームを切る。
- 翌日訪問予定の顧客のレポートは、前夜に事前生成する。当日の急な追加訪問だけリアルタイムで生成する。
ゲートウェイのタイムアウトを15分に延ばす案は、接続を長く保持し、アイドル接続が途中のネットワークで切れる危険も残るため不採用にしました。同じリクエストを同時に2つ送り、先に来た答えを使う案は、コストが2倍なので却下しました。修正後、失敗率は1%未満になり、重複生成はなくなりました。
松の香出版:最初からやり直さない校正パイプライン
出版社「松の香出版」は、単行本原稿を章に分けて校正案を作り、原稿管理システムに保存します。12冊・380章を処理した夜、529が続いて停止し、担当者は朝、最初からやり直しました。保存済みの章の校正結果が再保存され、2日分のコストが発生しました。ある章は高解像度のスキャン画像が多く、毎回サイズ上限超過の413で失敗し、リトライキューを塞ぎ続けていました。
プラットフォームエンジニアのチンさんは、パイプラインを組み直しました。
- 章ごとに状態(待機、進行、完了、失敗、隔離)を保存する。再起動時は完了済みの章をスキップする。
- 保存の冪等キーを
(原稿ID, 章番号, 校正回次)とする。同じキーが再び来たら既存の結果を返す。 - エラーを第4章の決定表で分ける。529・500・速度上限の429は予算内でリトライし、413・400はリトライせず即座にデッドレターキューへ送る。隔離された章は担当者が分割して再投入する。
- リリース前に障害注入試験を行う。処理途中でプロセスを強制終了して再起動し、重複保存がないか確認する。
全体をバッチAPIへ移す案も検討しました。コストは減りますが、編集者は朝から章順に確認します。バッチは最大24時間かかり、期限内に処理されない項目は期限切れになる可能性があるため、急がない再校正の回だけ使うことにしました。その後、障害があった日も、再起動後は残りの章だけを処理し、重複保存は1件もありませんでした。
間違えやすいポイント
- 「429は待てばすべて解消する」という誤解。 支出上限や日次クォータの429は、解除・調整まで失敗し続けます。本文のエラーコードで区別します。
- リトライは速く、回数が多いほどよいです。 失敗したリクエストも上限を消費します。バックオフ、ジッター、回数・時間の上限、リトライ予算が必要です。
- 400も何回か送り直せばよいです。 形式の問題は、修正するまで同じ結果になります。
- タイムアウトならサーバーで実行されていません。 結果不明です。変更操作は状態を照会してから再実行します。
- タイムアウトを延ばせば二重実行を解決できます。 頻度を減らすだけです。根本的な解決は冪等キーです。
- 「リトライごとに新しい冪等キーを作る」という誤解。 キーが変わると、受信側は同じ操作かわかりません。同じ操作のリトライには同じキーを使います。
- SDKに加えてアプリケーションもリトライすれば安全です。 回数が掛け算になり、障害を拡大します。リトライは1つの層で行います。
ひと目でわかるまとめ
| テーマ | 覚えておくこと |
|---|---|
| 結果の状態 | 成功・失敗・結果不明。結果不明の変更はまず照会 |
| リトライの判断 | 後で成功し得るか、繰り返して安全か、時間が残るか |
| 429 | 速度・急増は待ってリトライ、支出・クォータは停止・通知。Anthropicの自己設定上限は400 |
| レート制限 | トークンバケットなので短い急増でも制限される。徐々に増やす |
| バックオフ | 指数増加+ジッター+上限。Retry-Afterは最小待ち時間 |
| リトライの層 | 1か所だけ。SDKの既定値(Anthropicは2回)を確認 |
| タイムアウト | 接続・アイドル・全体の期限。長い処理はストリーミング・バッチ・バックグラウンド |
| 冪等性 | 全リトライで同じキー(ツール呼び出しID・業務識別子)+一意制約+結果保存。受信イベントも重複排除 |
| 部分的な失敗 | 成功を保持し、失敗は原因別に扱う。繰り返す失敗は隔離 |
| 障害の隔離 | 受け入れ制限、バルクヘッド、サーキットブレーカー、事前評価した代替経路 |
公式ドキュメントで確認する
- Anthropic — API errors:エラーの種類、SDKの自動リトライ、リクエストID、長いリクエストへの推奨を読む。
- Anthropic — Rate limits:トークンバケット、加速制限、支出上限の429、応答ヘッダーを確認する。
- OpenAI — Error codes:429の詳細な原因ごとにリトライすべきかを確認する。
- OpenAI — Rate limits:
Retry-After、ジッター、失敗リクエストによる上限消費を読む。 - IETF — RFC 9110 §9.2.2:冪等メソッドと自動リトライのルールを読む。
- AWS Builders' Library — Timeouts, retries, and backoff with jitter:タイムアウト設定、リトライの増幅、ジッターを読む。
セルフチェック
4-1. 応答を受け取れなかった変更リクエストを、「失敗」でなく「結果不明」と扱う理由と、その状態で行うことを順に書いてください。
4-2. 自動リトライを決める際、HTTPステータスコード以外に確認する情報を2つ挙げ、それぞれが判断を変える例を1つずつ書いてください。
4-3. トークンバケット方式と決まった時刻にリセットする方式の違いを説明し、分間総量が上限内でも拒否される理由を書いてください。
4-4. 接続タイムアウト、アイドルタイムアウト、全体の期限をそれぞれ定義し、長い生成処理でアイドルタイムアウトが単一のリクエストタイムアウトよりよい理由を書いてください。
4-5. 冪等キーを受け取る側(決済・予約サーバー)が保存すべき情報と、同じキーで内容の異なるリクエストが来た場合の処理を書いてください。
4-6. 1つのLLM APIをリアルタイム相談、文書要約、夜間分析の3機能で共有しています。機能別のリトライ予算、同時実行上限、タイムアウト、障害時の動作を定める表を設計してください。
実習課題
実習
障害注入付きのリトライラッパー(60分)
- モデル呼び出し前に偽の応答を挟む層を作る。
retry-after付き429、ヘッダーのない一時的429、支出上限のエラーコード付き429、529、500、400をランダムに混ぜる。 - 本章の決定表とバックオフ関数を実装し、SDKの自動リトライを無効にする。試行回数、総待ち時間、リトライ比率に予算を設ける。
- 100件のリクエストを送り、エラー種別ごとのリトライ回数、最終結果、リクエスト当たりの実際の送信回数を集計する。
完了基準: 400と支出上限のエラーコード付き429は一度もリトライされず、残りは予算内で回復するか代替経路へ進み、リクエスト当たりの最大送信回数が設計値を超えなければ完了とする。
実習
チェックポイントと冪等な保存を備えるパイプライン(60分)
- 30文書を1つずつモデルで処理して保存するジョブを作る。各文書の状態(待機、進行、完了、失敗、隔離)をファイルかDBに記録する。
- 保存は
(文書ID, 処理回次)を冪等キーとし、同じキーが再び来たら既存の結果を返す。 - 2文書は常にリトライ不可のエラーにしてデッドレターキューへ送り、15番目の処理中にプロセスを強制終了してから再実行する。
完了基準: 再実行後に完了済みの文書が再処理されず、ストレージに重複結果がなく、隔離した2文書が理由付きで一覧になれば完了とする。