みなさん、こんにちは!日々のインフラ構築やAPI設計、本当にお疲れ様です。ネットワークの裏側を覗き見ることが大好物な、技術メディア主筆ライターです。
私たちが普段何気なく使っているスマートフォンアプリやWebサービス。その裏側では、数えきれないほどのAPI(Webの窓口)が、休むことなくリクエストのやり取りを行っていますよね。
ところで、もしあなたが運営する人気WebサービスのAPIに、ある日突然、世界中から秒間10万件もの猛烈なアクセスが押し寄せてきたら……どうなるでしょうか?
そう、サーバーのCPUは悲鳴を上げ、メモリはパンクし、サービス全体が仲良くダウンしてしまいます。徹夜で復旧作業に追う悪夢の始まりです。
そんな悲劇を防ぐための「守護神」こそが、今回テーマにする「APIゲートウェイにおけるレートリミッティング(流量制限)アルゴリズム」です。
今回は、インフラやネットワークの世界に初めて足を踏み入れた初学者の方にもスッと腹落ちするように、身近な例えを交えながら、この奥深い制御の仕組みを一緒に解き明かしていきましょう!
—
1. なぜAPIゲートウェイで「交通整理」が必要なのか?
レートリミッティングという言葉を聞くと、なんだか難しそうに感じるかもしれません。でも、身の回りの現実世界を思い浮かべてみてください。
例えば、人気テーマパークのアトラクションや、大行列ができるラーメン屋さんを想像してください。
店員さんが「一度にお店に入れるのはここまでです」「次のご案内まで少しお待ちくださいね」と、入場制限をかけますよね。もしこの制限がなく、全員が我先にと厨房へ押し寄せたらどうなるでしょう? お店は一瞬で機能停止してしまいます。
Webの世界でも全く同じことが起きているんです。APIゲートウェイという「受付の番人」が、クライアント(利用者)からのリクエストの嵐を受け止め、「ちょっと早すぎます! 少し落ち着いてください(429 Too Many Requests)」と、適切な交通整理を行ってあげる必要があるのです。
では、この交通整理をシステムは具体的にどうやって行っているのでしょうか?
代表的な4つのアルゴリズムを、一歩ずつ見ていきましょう!
—
2. 代表的な4つのレートリミッティング・アルゴリズム
APIゲートウェイでよく使われるアルゴリズムには、それぞれ個性的な「キャラクター」があります。特徴を詳しく見ていきましょう。
① 固定ウィンドウ(Fixed Window)カウンター:一番シンプルだけど要注意?
もっとも直感的で実装しやすいのが、この「固定ウィンドウ」です。
例えば、「1分間に最大60リクエストまで」というルールを作ったとします。時計の針が「00分00秒」になったらカウンターをゼロにし、リクエストが来るたびに数字を「1、2、3……」とカウントアップしていきます。60に達したら、次の1分が来るまで門前払いにする仕組みです。
- メリット: とにかく仕組みがシンプルで、メモリをあまり消費しません。
- デメリット: 「境界線の問題」という弱点があります。例えば、1分間の最後の1秒間に60リクエストを使い切り、次の1分の最初の1秒間にまた60リクエストが来たらどうなるでしょう? 人間の目には「わずか数秒の間に120リクエスト」が集中しているように見えますが、カウンターのルール上はセーフになってしまい、サーバーに瞬間的な負荷がかかってしまいます。
② スライディングウィンドウ(Sliding Window)ログ:常に時間を監視する実力派
固定ウィンドウの「境界線の問題」をスマートに解決するのが、このスライディングウィンドウです。
これは、単純に「何分何秒から何分何秒」と区切るのではなく、「過去60秒間のスライドする時間枠」を常に監視し続ける方法です。
- メリット: 時間の偏りがなくなり、非常に滑らかで公平な制限ができます。
- デメリット: リクエストが来るたびに「過去の正確なタイムスタンプの履歴」を保存・計算し続ける必要があるため、メモリやCPUへの負荷が少し高くなります。
③ トークンバケット(Token Bucket):優しさと瞬発力を兼ね備えた人気者
ここからは、実務で本当によく使われる「バケット(バケツ)系」のアルゴリズムです。まずは「トークンバケット」から。
頭の中に、「一定の速度でチケット(トークン)が補充されるバケツ」を想像してください。
APIサーバーの隣にバケツがあり、そこに「1秒間に2枚のペース」で新しいチケットがポトポトと溜まっていきます(ただし、バケツの最大容量は10枚までと決まっています)。
ユーザーがAPIを叩くたびに、バケツからチケットを1枚取り出します。
- バケツにチケットが残っていれば:リクエスト大歓迎! 処理が進みます。
- バケツがからっぽなら:「チケットが足りません、少し待ってね」とエラーになります。
- メリット: バケツに最大容量(バースト許容量)があるため、「普段は静かだけど、たまにまとまったデータをごっそり送りたい」という正当なバースト通信(瞬発的な負荷)を優しく許容してくれます。
- デメリット: 特になし。バランスが非常に良いため、多くのAPIゲートウェイでデフォルト採用されています。
④ リーキーバケット(Leaky Bucket):お行儀よく一定のペースで流す職人肌
最後は「リーキーバケット(穴あきバケツ)」です。名前の通り、底に小さな穴が空いたバケツをイメージしてください。
ユーザーからのリクエスト(水)が、上からどれだけ大量にザバーっと注がれても、バケツがいっぱいになるまでは一旦すべて受け止めます。そして、底の穴から「一定の細い水流」のペースで、ポタポタと着実に処理されていきます。
もしバケツの容量を超えて水が注がれると、あふれた分は容赦なくこぼれ落ち(破棄され)ます。
- メリット: 下流のデータベースやバックエンドサーバーに対して、負荷が完全に一定(フラット)になります。サーバー側の計画が立てやすくなります。
- デメリット: ユーザーからすると、「今すぐ処理してほしいのに、一定のペースに強制的に待たされてしまう」という遅延(レイテンシ)が発生する原因になります。
—
3. 実装の現場から:Nginxを使った「トークンバケット」の設定例
理論がわかったところで、次は「インフラの現場でどう設定するのか」を覗いてみましょう。
世界中で大人気のWebサーバー兼リバースプロキシである Nginx を使って、APIゲートウェイにおけるシンプルなレートリミッティングを設定するサンプルを見てみます。
実務でそのままコピー&ペーストして調整できるように、日本語のコメントをたっぷり添えておきますね。
# httpコンテキスト(全体の基本設定エリア)
# 1秒あたり10リクエストを上限とする「my_rate_limit」という名前のバケツ(ゾーン)をメモリ上に作成します
# 1m というのは約16,000IPアドレス分の状態を保存できるメモリ領域です
limit_req_zone $binary_remote_addr zone=my_rate_limit:10m rate=10r/s;
server {
listen 80;
server_name api.example.com;
# APIへのリクエストを振り分ける場所
location /v1/ {
# 先ほど定義した制限を適用します
# burst=20 は「瞬間的に最大20リクエストまでの波(バースト)であれば受け付けるよ」という優しい猶予設定です
# nodelay をつけることで、猶予範囲内のリクエストは待たせずに即座に処理します
limit_req zone=my_rate_limit burst=20 nodelay;
# ここから後ろは実際のバックエンドサーバー(Node.jsやGoなど)への転送設定
proxy_pass http://backend_app_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
このように、インフラの設定ファイル一つをとっても、アルゴリズムの思想がそのままコードに落とし込まれているのが分かりますよね。「急なバーストをどこまで許容するか(burst)」や「遅延を許すか(nodelay の有無)」のチューニングは、まさにインフラエンジニアの腕の見せ所です。
—
4. アルゴリズム選定の指針:どれを選ぶべき?
「結局、自分のプロジェクトではどれを選べばいいの?」という疑問が湧いてきますよね。現場で迷ったときは、以下の基準を思い出してください。
1. 一般的なWeb APIやSaaSの公開:
- ⇒ 「トークンバケット」 または 「スライディングウィンドウ」 が第一候補です。ユーザーの使い心地(UX)を損なわず、正当なアクセスの波を受け止められます。
2. 決済システムや絶対に落としたくない高負荷バッチ連携:
- ⇒ 「リーキーバケット」 でバックエンドの入力スピードをガチガチに制御し、サーバーを守るのが安全です。
3. とにかく実装をサクッと終わらせたい初期のプロトタイプ:
- ⇒ 「固定ウィンドウ」 から始めて、アクセスが増えてきたら上位のアルゴリズムへ移行するのも立派な戦略です。
—
まとめ:ネットワークの優しさはアルゴリズム宿る
今回は、APIゲートウェイにおけるレートリミッティングの仕組みを、身近な例えとNginxの設定を交えて紐解いてきましたがいかがでしたでしょうか?
一見すると無機質なエラーコードや設定パラメータの裏側には、「サーバーの安全を守りたい」「だけどユーザーには快適に使ってほしい」という、設計者たちの温かい工夫(アルゴリズム)がしっかりと詰まっています。
ネットワークやインフラストラクチャの世界は、こうした「現実世界の見立て」をコードに翻訳していく知的でワクワクする冒険の連続です。ぜひ今回の記事を参考に、ご自身の環境でも美しい流量制限のデザインに挑戦してみてくださいね!
それでは、また次の深淵でお会いしましょう。良きインフラライフを!
コメント