Just another IT site ※IT系の記事は当方環境での実施内容となるため実施する場合は自己責任でお願いいたします。At Your Own Risk!! TURN BACK WHILE YOU CAN
PR

夜間保守のバディ 第29話 429 Too Many Requests

※IT系の記事は当方環境での実施内容となるため実施する場合は自己責任でお願いいたします。スクリプトはAI生成のものも多いのでコピー&ペーストの際は文字コードに注意ください!
AI連載小説

API連携が突然失敗した。ステータスは429。瀬名は先方障害を疑ったが、律は自分たちのリクエスト数を数えた。

再試行処理が短い間隔で走り、失敗するほどさらに叩く実装になっていた。典型的なリトライ嵐だった。

二人は指数バックオフを入れ、`Retry-After` を尊重するよう修正した。監視にも429率を追加した。

「焦って何度も聞くほど、相手に閉じられる」

律が言うと、瀬名は苦笑した。

「耳が痛いです」

「何か心当たりが?」

「あります」

瀬名が正直に答えると、律は一瞬だけ目を丸くした。聞き返さない優しさが、そこにあった。


人物紹介
瀬名悠真

  • 男性、30代
  • サーバ運用・インフラ担当
  • 手は動くが、初動で少し焦りやすい

久坂律

  • 女性、30代
  • 監視、自動化、ログ解析、運用設計に強い
  • 冷静で、原因調査の順序を大事にする

用語メモ

 

HTTP 429(Too Many Requests)エラーにおける「指数バックオフ」「Retry-After」を組み合わせたリトライ設計は、サーバーの過負荷(バースト)を防ぐための世界標準のベストプラクティスです。
その仕組み、重要性、具体的なアルゴリズムを解説します。

1. 各要素の役割
HTTP 429 (Too Many Requests) とは?
サーバーが設定したリクエスト数の上限(レートリミット)を超えたことを示すエラーです。
「これ以上リクエストを送らないでください」というサーバーからの警告を意味します。
Retry-After ヘッダーとは?
HTTP 429 応答時に、サーバーがクライアントに対して「あと何秒(または何時まで)待てば再送してよいか」を明示するヘッダーです。
    • 秒数指定の例: Retry-After: 30 (30秒待て)
    • 日時指定の例: Retry-After: Fri, 31 Dec 2026 23:59:59 GMT

指数バックオフ(Exponential Backoff)とは?
リトライの回数に応じて、待機時間を「2秒 → 4秒 → 8秒 → 16秒…」のように指数関数的に増やしていくアルゴリズムです。
これに「ジッター(Jitter)」と呼ばれるランダムな誤差を加えるのが一般的です。

2. 組み合わせて使う理由(なぜ両方必要なのか?)
サーバーの親切心(Retry-After)と、クライアントの自衛(指数バックオフ)を組み合わせることで、最も堅牢なシステムが作れます。
    1. サーバーの指示を最優先するため
      サーバーが「10秒待て」と言っているなら、アルゴリズムによる計算(例:2秒)を無視して10秒待つのが最も安全です。
    1. ヘッダーがない場合のフォールバック(予備)のため
      すべてのサーバーが Retry-After を返してくれるとは限りません。ヘッダーがない場合は、クライアント側で計算した指数バックオフの待ち時間を適用します。
    2. 複数クライアントの衝突(同期現象)を防ぐため
      もし数千台のスマホアプリが同時に 429 エラーになり、全員が Retry-After: 10 に従って「ぴったり10秒後」に一斉再送すると、サーバーが再びダウンします。これを防ぐために、ランダムな秒数(ジッター)を足し引きしてアクセスを分散させます。


3. リトライ処理の標準的なフロー(ロジック)
プログラムが HTTP 429 を検知したとき、以下の優先順位で待機時間(ウェイト)を決定します。
text
[HTTP 429 エラー発生]
       │
       ▼
① レスポンスに `Retry-After` ヘッダーはあるか?
   ├──【YES】 サーバー指定の秒数を採用する
   └──【NO】  ② 指数バックオフの計算式を適用する
            (待ち時間 = 基本待ち時間 * 2^(リトライ回数) + ランダムな揺らぎ)
       │
       ▼
③ 決定した時間だけ待機(スリープ)
       │
       ▼
④ リトライ実行(上限回数に達するまで繰り返し)
コードは注意してご使用ください。


4. 具体的なコードイメージ(擬似コード)
python
import time
import random

def request_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        response = send_request(url)
        
        # 成功ならデータを返す
        if response.status_code == 200:
            return response.data
            
        # レートリミット(429)に達した場合
        if response.status_code == 429:
            wait_time = 0
            
            # ① Retry-After ヘッダーの確認
            if "Retry-After" in response.headers:
                wait_time = parse_retry_after(response.headers["Retry-After"])
            
            # ② ヘッダーがない場合は指数バックオフ+ジッター
            else:
                base_wait = 2  # 初期待ち時間(2秒)
                # 指数バックオフの計算 + フルジッター(0〜計算値の間のランダム)
                calculated_wait = base_wait * (2 ** attempt)
                wait_time = random.uniform(0, calculated_wait)
            
            print(#秒待機して再試行します)
            time.sleep(wait_time)
            continue
            
    raise Exception("リトライ上限を超えました")
コードは注意してご使用ください。

タイトルとURLをコピーしました