レート制限は『API を持続可能にする』設計
レート制限はDoS対策・公平な利用・コスト保護の3つを兼ねます。本記事では編集部の視点で、アルゴリズムと分散環境での実装を公開情報をもとに整理します。REST API設計 もご参考に。
4つの基本アルゴリズム
(1) Fixed Window:固定時間枠でカウント。実装は簡単だが境界で2倍流入する欠点。(2) Sliding Window Log:リクエスト時刻を全保存。正確だがメモリ消費大。(3) Sliding Window Counter:前枠と今枠の比例配分。バランス良。(4) Token Bucket:バーストを許容しつつ平均速度を制御。(5) Leaky Bucket:一定速度で流出。バースト吸収。
Token Bucket の実装
(1) capacity:バケットの容量。バースト許容量。(2) refill_rate:毎秒n個追加。(3) 消費可否を原子的に判定:CAS や Lua スクリプト。(4) Redis での実装:INCR + EXPIRE は近似実装。(5) 正確な実装:Lua スクリプトで TOKENS と LAST_REFILL を管理。
分散環境での課題
(1) 状態共有:複数サーバーで同じカウンタを参照。(2) Redis 集約:単一の真実源。(3) レイテンシ:Redis 往復で数ms増。(4) ノード障害:Redis障害時はフォールバック必要。(5) 近似アルゴリズム:HyperLogLog 等で大規模対応。
HTTPレスポンスの規約
(1) 429 Too Many Requests:制限超過時。(2) Retry-Afterヘッダ:再試行可能までの秒数。(3) X-RateLimit-Limit / Remaining / Reset:標準的なヘッダ。(4) エラーメッセージ:原因を簡潔に。(5) ドキュメント化:消費者にも知らせる。Observability 実践 でレート制限ヒット率を計測。
制限軸の設計
(1) IP単位:未認証API向け。(2) APIキー/ユーザー単位:認証API向け。(3) エンドポイント単位:重い処理を厳しく。(4) プラン単位:Free/Pro/Enterprise で差をつける。(5) 複合軸:上記を組み合わせ。認証・認可実践 も合わせて。
失敗しがちなパターン
(1) Fixed Window で境界バースト:1分0秒に集中流入。(2) Redis 単一障害:制限機能停止。(3) 制限値が緩すぎる/厳しすぎる:監視で調整。(4) 403 で返す:429 を使うべき。(5) 制限ヘッダなし:クライアントが適応できない。対策は、(1)Token Bucket推奨、(2)Redis HA、(3)使用量分析、(4)429+Retry-After、(5)標準ヘッダ送信、です。