レートリミット
レートリミットとは
レートリミット(rate limiting)は、一定時間あたりに受け付けるリクエスト数を制限する仕組みです。「1ユーザーにつき毎分60回まで」のようなルールを設け、超過した分は拒否します。
目的は大きく3つです。
- 過負荷の防止 — 一部の利用者の大量リクエストでサーバー全体が遅くなるのを防ぐ
- 攻撃の抑制 — パスワードの総当たりや [[DDoS攻撃と対策]] で扱うような大量アクセスの被害を軽減する
- 公平性と課金 — API の利用プランごとに呼び出し回数の上限を設ける
制限に達したときの応答
制限を超えたリクエストには、[[HTTPステータスコード]] の 429 Too Many Requests を返すのが標準です。あわせて次のようなヘッダーで「あとどれくらい待てばよいか」を伝えます。
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
呼び出す側の作法も重要です。429 を受けたら Retry-After に従って待ち、リトライの間隔を徐々に延ばす指数バックオフ(exponential backoff)を使うのが定石です。間隔を空けずに再送し続けると、制限がさらに長引くだけです。
代表的なアルゴリズム
| 方式 | 考え方 |
|---|---|
| 固定ウィンドウ | 「毎分0秒からの1分間で60回まで」と区切って数える。実装が簡単だが区切り目に偏りが出る |
| スライディングウィンドウ | 「直近60秒間で60回まで」と常に直近を数える。偏りが少ない |
| トークンバケット | 一定速度でトークンが補充され、リクエストごとに消費。短時間のバースト(瞬間的な集中)を許容できる |
カウンタは複数サーバーで共有する必要があるため、[[Redis]] のような高速な共有ストアで実装するのが定番です。また、個々のサービスではなく [[APIゲートウェイ]] で一括して制限をかける構成が広く使われます。
初学者向けポイント
- 外部 API を呼ぶ側になったときこそレートリミットを意識しましょう。429 を想定しないコードは本番で必ず壊れます
- 制限の単位(IPアドレスか、APIキーか、ユーザーか)で挙動が大きく変わります。共有オフィスの同一IPで巻き添えを食うのは典型例です
- 自分の [[REST API]] を公開するなら、最初から上限とレスポンスヘッダーをドキュメントに明記するのが親切です
関連技術とのつながり
- [[APIゲートウェイ]] — レートリミットを一括で適用する定番の場所
- [[REST API]] — 制限の対象。429 の扱いは API 設計の一部
- [[DDoS攻撃と対策]] — 大量アクセスへの防御としての側面
- [[Redis]] — 複数サーバーで共有するカウンタの実装先
- [[冪等性]] — 429 後のリトライを安全にする前提。再送しても二重処理にならない設計が要る
- [[エラーハンドリングとリトライ設計]] — 429 に限らない再試行の作法。上限とジッターの決め方
Q: レートリミット超過時に返す標準的なHTTPステータスコードはどれ?
- [ ] 404 Not Found
- [x] 429 Too Many Requests
- [ ] 301 Moved Permanently
解説: 回数制限の超過には 429 を返し、Retry-After ヘッダーで待ち時間を伝えるのが標準です。
Q: 429を受け取ったクライアントの正しい振る舞いはどれ?
- [ ] 間隔を空けず成功するまで再送し続ける
- [x] Retry-Afterに従って待ち、指数バックオフでリトライ間隔を延ばす
- [ ] リクエストの送信元IPを偽装して再送する
解説: 待たずに再送しても制限が長引くだけです。指数バックオフで間隔を徐々に延ばすのが定石です。
Q: 短時間のバーストを許容できるアルゴリズムとして本文で挙げられているのはどれ?
- [ ] 固定ウィンドウ
- [ ] 単純なブラックリスト方式
- [x] トークンバケット
解説: トークンバケットは貯まったトークンの分だけ瞬間的な集中を許容しつつ、平均速度を制限できます。