レートリミットとリトライ — 断るのは優しさ
人気のAPIに、世界中のアプリが一斉にリクエストを投げてきたらどうなるでしょう。サーバーはパンクします。そこで「1秒あたり何回まで」と流量に上限を設ける仕組みがレートリミット(Rate Limit)です。代表的な方式がトークンバケツ。バケツに一定ペースでトークン(通行券)が補充され、リクエストは1回につき1枚消費します。トークンが空なら、その場で断られます(429 Too Many Requests)。
断られた側はどうすればいい? すぐ投げ直しても、まだ空なら また断られます。賢いのは少し待ってから再試行(リトライ)し、それでもダメなら待ち時間を倍々に伸ばすこと。これを指数バックオフと呼びます。下の図1で、トークンが補充される様子を見ながらリクエストを送ってみてください。
なぜ「断る」ことが優しさなのか
上限なく受け付けてサーバーごと倒れると、全員のリクエストが失敗します。早めに「今は無理」と断れば、サーバーは生き残り、落ち着いたユーザーには応え続けられます。レートリミットは意地悪ではなく、全体を守るための交通整理です。だからクライアント側も、断られたら怒って連打するのではなく、間隔を空けて再試行するのが礼儀でありお得でもあります。
再試行のとき、全クライアントが「ちょうど1秒後」に揃って投げ直すと、また同時に殺到してしまいます(これをサンダリングハードと呼びます)。そこで実務では待ち時間に少しランダムなブレ(ジッター)を足し、再試行のタイミングをばらけさせます。
- レートリミット
- 一定時間あたりのリクエスト回数に上限を設け、過負荷を防ぐ仕組み。
- トークンバケツ
- 一定ペースで補充される通行券を消費して通す方式。短いバースト(連打)もある程度許容できる。
- 429
- HTTP「Too Many Requests」。上限超過で断られたことを示すステータスコード。
- 指数バックオフ
- 再試行のたびに待ち時間を倍々(1s→2s→4s…)に伸ばす方式。ジッターを足すとさらに安全。
まとめ
レートリミットは「流量に上限を設けて全体を守る」仕組み、リトライは「断られても賢く待って投げ直す」作法です。図1で 5件連打すると、はじめの数件は通り、トークンが尽きた瞬間から 429 で弾かれるのが見えます。自動リトライをONにして連打すると、補充を待ってから順に成功していく — この「待つ」判断こそが、サーバーにもクライアントにも優しい振る舞いです。