こんにちは!ネットワークの深淵をこよなく愛するエンジニアです。
今日は、Web APIの設計において「これを知っているか否か」で、あなたのAPIが「品格のあるサービス」になるか、「すぐにダウンする迷惑なサービス」になるかを分ける重要なテーマ、429 Too Many Requestsについてお話しします。
「APIをたくさん叩きすぎるとエラーになるのは知っているけれど、具体的にどう振る舞うのが正解なの?」という疑問、皆さんも一度は持ったことがあるのではないでしょうか。
今日は、小難しい仕様書の解釈ではなく、郵便配達員さんと私たちの家のポストを例に、この「大人のマナー」を紐解いていきましょう。
—
1. 郵便配達員さんがパニックを起こさないために
想像してみてください。あなたは今、人気の通販サイトの運営者です。毎日たくさんの注文が届きますよね。
ある日、一人の熱狂的なファンが、1秒間に100通もの手紙をあなたのポストに放り込んできたとしたらどうでしょう? あなたは手紙を開封するのに必死で、他の普通の注文をさばく余裕がなくなってしまいますよね。
これがネットワークの世界で言うところの「DoS攻撃(サービス拒否攻撃)」や「過剰なリクエスト」です。
そこで登場するのが、429 Too Many RequestsというHTTPステータスコードです。これは「君の熱意は嬉しいけれど、ちょっと早すぎるよ! 少し待ってからまた来てくれるかな?」という、サーバーからの「やんわりとしたお断り」なんです。
2. ただ断るだけじゃない、「思いやり」のヘッダー Retry-After
単に「ダメ!」と追い返すだけでは、クライアント(アプリやサービス)は「じゃあいつならいいの?」と路頭に迷ってしまいます。そこで登場するのが Retry-After という魔法のヘッダーです。
これは、郵便配達員さんに「今は忙しいから、あと30秒たってから戻ってきてね」とメモを渡すようなもの。これを受け取った側は、闇雲に再試行(リトライ)を繰り返すのではなく、サーバーの指示に従って賢く待機できるわけです。
3. 実践! サーバー側はどう実装すべきか
では、実際にAPIサーバーを開発する際に、どのような心構えで実装すればよいかを見ていきましょう。今回はPythonのWebフレームワーク「FastAPI」を例に、概念的なコードを見てみますね。
from fastapi import FastAPI, HTTPException, Request
import time
app = FastAPI()
# 簡易的なレート制限のメモリ管理
request_history = {}
@app.get("/api/data")
async def get_data(request: Request):
client_ip = request.client.host
# ここでは簡略化していますが、実際はRedisなどを使って制限を管理します
# もし制限を超えていたら...
if is_over_limit(client_ip):
# 30秒後に再試行してほしいと伝える
headers = {"Retry-After": "30"}
# 429ステータスコードと共に、丁寧なお断りを返す
raise HTTPException(
status_code=429,
detail="リクエストが多すぎます。30秒後に再度アクセスしてください。",
headers=headers
)
return {"message": "データをお届けします!"}
このコードのポイントは、headers={"Retry-After": "30"} です。これがあるだけで、クライアント側は無駄な通信を控え、サーバーが回復するのを静かに待つことができるようになります。
4. クライアント側(呼び出す側)の作法
逆に、あなたがAPIを利用する側だったらどうすべきでしょうか?
一番やってはいけないのは、429が返ってきた瞬間に「エラーだ!すぐにもう一回リトライだ!」と即座に再試行することです。これではサーバーをさらに追い詰める「追撃」になってしまいます。
現場では、「指数バックオフ」というアルゴリズムを使うのが一般的です。
1. 429を受け取る。
2. Retry-After ヘッダーを確認する。
3. 指定された時間(なければ数秒から始め、失敗するたびに待機時間を倍にしていく)だけ待つ。
4. 再度リクエストを送る。
この手順を守るだけで、あなたのプログラムは「サーバーに優しい、行儀の良いクライアント」として評価されるようになります。
まとめ:ネットワークは「対話」である
Web APIは、単なるデータのやり取りではありません。サーバーとクライアントの間で行われる「対話」です。
相手が忙しそうなら少し待つ。こちらが忙しいときは、相手に「あとこれくらい待ってね」と伝える。この気遣いこそが、スケーラブルで信頼されるインフラを作るための第一歩です。
429 Too Many Requests は、決して「拒絶」ではありません。より良いサービスを継続するための「調整」のシグナルなのです。ぜひ、皆さんの開発現場でも、この「思いやりのあるエラーハンドリング」を取り入れてみてくださいね。
また次回の技術ブログでお会いしましょう!ネットワークの旅はまだまだ続きます。
コメント