サーバーレスアプリケーションにおけるレート制限の重要性と実装方法
サーバーレスアーキテクチャの最大の魅力のひとつは、大規模なトラフィック急増時にも自動的にスケールできる点です。しかし残念ながら、スケーリングは金銭的にも技術的にも「無料」ではありません。そのため、開発者はアプリケーションのスケーラビリティを適切に制御する必要があります。
ここでは、サーバーレスアプリケーションにレート制限(Rate Limiting)メカニズムが必要となる主な理由を3つ紹介します。
レート制限が必要な3つの理由
1. リソースの保護
公開APIを提供している場合、トラフィックの急増はサービス品質の低下を招き、最悪の場合、全ユーザーに対するサービス停止につながる可能性があります。カスケード障害や、意図せず発生する自己DDoS的なインシデントからシステムを守らなければなりません。アプリケーションのバグがこうした問題の引き金になることもあります。例えば、障害発生時にエンドポイントへの再試行を無限に繰り返す内部プロセスは、あっという間にリソースを枯渇させてしまうでしょう。
2. ユーザークォータの管理
サービスの公平な利用を実現するため、ユーザーごとに利用枠(クォータ)を定義したいケースがあるでしょう。また、料金プランを複数のティアで提供している場合にも、クォータ管理は不可欠です。
3. コストの制御
制御されていないシステムが高額な請求を引き起こした実例は、現実に数多く存在します。高いスケーラビリティを持つサーバーレスアプリケーションにとって、これは特に大きなリスクです。レート制限を導入することで、こうしたコストを効果的に管理できます。
レート制限の3つの解決策
レート制限には、異なるレイヤーで実装できる複数の選択肢があります。ここでは代表的な3つの手法を、それぞれの長所・短所とともに比較します。
1. 関数の同時実行数(Concurrency)制限
クラウドプロバイダーは、サーバーレス関数の実行をスケールさせるために複数のコンテナを作成します。同時に稼働するコンテナ/インスタンスの最大数には上限を設定できます。AWS Lambda および Google Cloud Functions のいずれでも同時実行数の制限が可能です。
長所:
- オーバーヘッドなし
- 設定が簡単
短所:
- 完全なソリューションではない。同時実行数しか制御できず、1秒あたりの実行回数は制限できない。
2. API Gatewayでのレート制限
関数へAPI Gateway経由でアクセスしている場合は、API Gateway側にレート制限ポリシーを適用できます。AWS と GCP の両方に公式の設定ガイドが用意されています。
長所:
- オーバーヘッドなし
- 設定が簡単
短所:
- API Gatewayを使用している場合にのみ適用可能。
- ユーザー単位・IP単位のクォータなど、より高度な要件には対応していない。
3. Redisによるレート制限
最も完成度が高く、柔軟性に優れたソリューションがこれです。Redisベースのレート制限ライブラリは多数存在します。Jeremy Daly氏のブログ記事では、Elasticacheを候補から除外しており、その理由として「『非サーバーレス』なコンポーネントが増え、管理対象がひとつ増えてしまう」と述べています。そこで注目したいのがUpstashです。サーバーレスモデルとリクエスト単位の従量課金により、非常に有力な代替手段となります。
長所:
- 強力。自社のユーザーモデルに合わせたカスタムロジックを実装できる。
- スケーラブル。GitHubがRedisでレート制限を実装した事例も参考になる。
- 豊富なエコシステム。redis_rate、redis-cell、node-ratelimiter など多数のオープンソースライブラリが存在。
短所:
- Redisを運用するためのオーバーヘッドが発生する。
コード例:Redisによるレート制限
レート制限ライブラリを活用すれば、アプリケーションコードへの組み込みは非常に簡単です。以下のサンプルコードは、IPアドレスごとに5秒間で1回までという制限をAWS Lambda関数に適用したものです。
const RateLimiter = require("async-ratelimiter");
const Redis = require("ioredis");
const { getClientIp } = require("request-ip");
const rateLimiter = new RateLimiter({
db: new Redis("YOUR_REDIS_URL"),
max: 1,
duration: 5_000,
});
module.exports.hello = async (event) => {
const clientIp = getClientIp(event) || "NA";
const limit = await rateLimiter.get({ id: clientIp });
if (!limit.remaining) {
return {
statusCode: 429,
body: JSON.stringify({
message: "Sorry, you are rate limited. Wait for 5 seconds",
}),
};
}
return {
statusCode: 200,
body: JSON.stringify({
message: "hello!",
}),
};
};
完全な実装例については、チュートリアルをご覧ください。
参考文献
- Google Cloud — Rate limiting strategies and techniques
- Jeremy Daly — Throttling third-party API calls with AWS Lambda
- Google Cloud — Rate limit your API usage with Cloud Endpoints quotas
- GitHub Blog — How we scaled GitHub API with a sharded, replicated rate limiter
- Redis — INCR command: Rate limiter pattern
- Stripe Blog — Scaling your API with rate limiters
-
Windows 10でRAM(メモリ)を解放する9つの方法|メモリ不足・動作の重さを解消
お使いのWindows 10パソコンに「システムのメモリが不足しています」という警告が表示されていませんか? あるいは、メモリ使用量の増加によりシステムがフリーズしたり固まったりしていませんか? ご安心ください。このガイドでは、Windows 10パソコンのRAMを解放する9つの方法を詳しく解説します。ゆっくり歩く人、大きな音を立てて食べる人、旅行の遅延、不安定なWi-Fi接続、そして動作の重いパソコン――世界で最もストレスを感じるもののひとつに、パソコンの動作の遅さが挙げられます。実は、ストレージに十分な空き容量があっても、パソコンの動作が遅くなることがあります。複数のアプリケーションを効率
-
Macのデフォルトアプリを変更する方法|カレンダー・メール・ブラウザ・画像ビューアの設定手順を解説
Macには標準で使いやすいアプリケーションが多数搭載されています。しかし、標準アプリでは足りない機能がある、またはやりたい操作に対応していないといった場面に遭遇することもあるでしょう。そんなときは、お好みのサードパーティ製アプリを「デフォルト(既定)アプリ」として設定することで、快適な作業環境を構築できます。 この記事では、Macのカレンダー、メール、Webブラウザ、画像ビューアの各デフォルトアプリを変更する具体的な手順を、初心者にもわかりやすく解説します。 Macのデフォルトカレンダーアプリを変更する方法 まずは、Macの標準カレンダーアプリを別のアプリに変更する手順から見ていきましょう。