目次
アプリケーションシナリオ
1. 過剰なトラフィックによるシステム クラッシュの防止: トラフィックが突然増加した場合、フロー制限により、システムがリソースを使い果たしたり、過剰なトラフィックによってクラッシュしたりすることがなくなります。
2. 悪意のあるリクエストの防止: 電流制限を使用して一部の悪意のあるリクエストを制限し、これらのリクエストがシステムに損害を与えるのを防ぐことができます。
3. スレッド プールの枯渇を回避する: リクエストが多数ある場合、バックエンド スレッド プールが枯渇し、その結果、多くのリクエストが応答されなくなる可能性があります。スロットリングを追加すると、この問題の発生を防ぐことができます。
4. キャッシュの故障を防ぐ: キャッシュが故障すると、バックエンド システムは大量のリクエストを受信します。スロットリングにより、バックエンド システムがキャッシュの無効化によって圧倒されないようにすることができます。
5. トラフィックの同時実行性の制御: 一部のシステムは、独自の処理能力に基づいて同時実行性を制御しますが、電流制限によりトラフィックと同時実行性を制御できます。
共通の戦略
1. クライアント電流制限: サーバーに対するクライアント要求の頻度を制限します。これは、クライアント側に電流制限アルゴリズムを実装することで実現できます。
2. サーバー側の電流制限: サーバーによるリクエストの処理頻度を制限します。これは、サーバーに電流制限を実装することで実現できます。
3. アプリケーション層の電流制限: アプリケーション層は、ビジネス ロジックに基づいて特定のリクエストの電流フローを制限します。たとえば、重要なリソースへのアクセス頻度を制限します。
4. ネットワーク層の電流制限: ネットワーク デバイスでトラフィック制御を実行し、サーバーに到着するリクエストの頻度を制限します。
よく使われるテクニック
1. カウンタ: カウンタを使用してリクエストの数をカウントし、しきい値に達するとリクエストは拒否されます。これは、Java の AtomicInteger を使用してカウンターを実装できる単純な電流制限メソッドです。
2. スライディング ウィンドウ: 固定サイズのウィンドウを維持し、ウィンドウ内のリクエストの数をカウントし、しきい値に達した場合はリクエストを拒否します。このメソッドは単純なカウンターよりも正確であり、Java の LinkedBlockingQueue を使用してスライディング ウィンドウを実装できます。
3. リーキー バケット アルゴリズム: バケットのサイズを維持します。バケットがいっぱいの場合はリクエストが拒否され、そうでない場合はリクエストが解放されます。リーキー バケットのサイズによって電流制限レートが制御され、Java のセマフォを使用してリーキー バケット アルゴリズムを実装できます。
4. トークン バケット アルゴリズム: トークンは定期的に生成され、バケットに入れられます。バケット内にトークンがある場合、リクエストは許可され、1 つのトークンが消費されます。そうでない場合、リクエストは拒否されます。トークン生成のレートによって電流制限レートが制御され、Java の ScheduledExecutorService と Semaphore を使用してトークン バケット アルゴリズムを実装できます。
5. Guava の RateLimiter: Google Guava の RateLimiter はトークン バケット アルゴリズムを実装しており、直接使用できます。シンプルで使いやすい電流制限機能を提供し、同時リクエストを適切にサポートします。
コード
カウンター
public boolean limit() {
count++;
if (count > threshold) {
return false; // 达到限流阈值,拒绝请求
}
return true;
}
スライドウィンドウ
Deque<Long> window = new ArrayDeque<>();
long now = System.currentTimeMillis();
window.add(now);
if (window.size() > windowSize) {
long oldest = window.pollFirst();
if (now - oldest < interval) {
return false; // 窗口内请求数达到限流阈值,拒绝请求
}
}
return true;
リーキーバケットアルゴリズム
Semaphore semaphore = new Semaphore(bucketSize);
if (semaphore.tryAcquire()) {
return true; // 获取令牌成功,放行请求
}
return false; // 桶中无令牌,拒绝请求
トークンバケットアルゴリズム
ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);
Semaphore semaphore = new Semaphore(0);
scheduled.scheduleAtFixedRate(() -> {
int added = Math.min(bucketSize - semaphore.availablePermits(), addRate);
semaphore.release(added); // 按速率添加令牌
}, 0, 1, TimeUnit.SECONDS);
if (semaphore.tryAcquire()) {
return true; // 获取令牌成功,放行请求
}
return false; // 桶中无令牌,拒绝请求
グアバレートリミッター
RateLimiter limiter = RateLimiter.create(2); // 每秒 2 个请求
if (limiter.tryAcquire()) {
return true; // 获取令牌成功,放行请求
}
return false; // 限流,拒绝请求
長所と短所
これらの電流制限手法にはそれぞれ長所と短所があります。
1. カウンター:
- 利点: シンプルで実装が簡単
- 欠点: 精度が十分ではない、レートを制御できない、ウィンドウ サイズを構成できない
2. スライディングウィンドウ:
- 利点: カウンタよりも正確で、ウィンドウ サイズを設定可能
- 短所: 実装の複雑さはカウンターよりも高い
3. リーキーバケットアルゴリズム:
- 利点: レートを制限でき、実装が簡単
- 短所: 突然の渋滞に対処できるほど正確ではありません
4. トークンバケットアルゴリズム:
- 利点: レートを制限でき、バースト トラフィックに対処できる
- 短所: 実装がより複雑
5.グアバレートリミッター:
- 利点: 実装が簡単、レートを制限でき、突然のトラフィックに対処できる
- 短所: レート制御は十分な柔軟性がなく、より複雑な電流制限戦略を実装できません。
要約すると、私の推奨事項は次のとおりです。単純な電流リミッターが必要な場合は、Guava RateLimiter を使用してください。導入も簡単で機能も十分です。より正確なレート制御が必要な場合、またはより複雑な電流制限戦略を実装する場合は、トークン バケット アルゴリズムに基づいて独自の電流リミッターを実装します。電流制限の精度が高くない場合は、単純なカウンターまたはスライディング ウィンドウを使用できます。アプリケーションのシナリオに基づいて、適切な電流制限テクノロジを選択することが非常に重要です。すべてのシナリオに適したテクノロジーは存在しないため、各テクノロジーの長所と短所を理解することが重要です。さらに、多次元から電流制限を実行することもできます。
例えば:
- 特定のユーザーのフローを制限する
- 特定のリソースの流れを制限する
- クライアントIPに基づいてトラフィックを制限する
- など。そのため、電流制限システムを設計するときは、これらの要素を十分に考慮する必要があります。
アプリケーションシナリオ
1. カウンター:
- シナリオ: 単純な電流制限器が必要ですが、高い電流制限精度は必要ありません。
- 例: リソースの盗難を防ぐために、リソースへのアクセス数を制限します。
- フレームワーク: シンプルなアプリケーション層の電流制限実装
2. スライディングウィンドウ:
- シナリオ: 特定のウィンドウ内のリクエストの数を制限する必要があり、ウィンドウ サイズは構成可能です。
- 例: ブルート フォース ログイン試行を防ぐために、特定の時間枠内でのログイン失敗の数を制限します。
-フレームワーク: Nginx およびその他のプロキシ サーバー
3. リーキーバケットアルゴリズム:
- シナリオ: ある程度のバースト トラフィックに対処するには、リクエストを固定レートで制限する必要があります。
- 例: トラフィックの突然の増加によるシステムの過負荷を防ぐために、インターフェイス呼び出しの速度を制限します。
- フレームワーク: Hystrix およびその他のフォールト トレラント ライブラリ
4. トークンバケットアルゴリズム:
- シナリオ: リクエストの通過速度をより正確に制御し、より高いバースト トラフィックに対処できるようにする必要があります。
- 例: 突然の大規模なトラフィックによってリソースが過負荷にならないように、重要なリソースへのアクセス レートを制限します。
- フレームワーク: Sentinel、Resilience4j、その他のフロー制御フレームワーク
5.グアバレートリミッター:
- シナリオ: 単純なレート リミッタが必要ですが、正確なレート制御や複雑な電流制限戦略は必要ありません。
- 例: API 呼び出しの頻度を単純に制限して、過剰なサーバー リソースが占有されるのを防ぎます。
-フレームワーク: Google Guava
さらに、電流制限テクノロジーは他の製品やフレームワークでも使用されています。
- AWS WAF: レート制限とウェブファイアウォールに基づいて悪意のあるトラフィックを制限します。
- Nginx 電流制限モジュール: レート制限とリーキー バケット アルゴリズムに基づく電流制限
- Envoy Router: レート制限とトークン バケット アルゴリズムに基づいてトラフィックを制限します。
- API ゲートウェイ: 通常はレート制限に基づいて、API リクエストのフローを制限します。
- データベース エージェント: レート制限とリーキー バケット アルゴリズムに基づいて、データベース接続の数とクエリ頻度を制限します。
- キャッシュ プロキシ: レート制限とトークン バケット アルゴリズムに基づいて、キャッシュ ブレークダウン シナリオでのリクエスト トラフィックを制限します。
-など
これらの電流制限テクノロジーは多くのシナリオに適用できることがわかりますが、各テクノロジーには最適なシナリオがあります。電流制限テクノロジーを選択するときは、次の点を考慮する必要があります。
- 制御する必要があるオブジェクト (ユーザー、リソースなど)
- 電流制限精度要件 (レート制御が正確かどうか)
- バースト トラフィックに対処する必要がありますか?
- 電流制限戦略の複雑さ
-など
最適な電流制限テクノロジを選択する前に、これらの要素を考慮してください。
ツールクラスのカプセル化
コード パッケージ内のこのツール クラスは、カウンタ電流制限、スライディング ウィンドウ電流制限、リーキー バケット電流制限、およびトークン バケット電流制限の 4 つのメソッドを実装します。必要に応じて、フロー制御に対応する電流制限方法を選択できます。複数の電流制限テクノロジを統合するこのようなツール クラスは、電流制限アルゴリズムを毎回自分で実装する必要がなく、さまざまな電流制限シナリオに適切に適用できます。
注: ここでのトークン バケットとリーキー バケットの現在の制限は、スレッド数レベルでの現在の制限であり、ビジネス レベルでのデータ速度制限には使用できません。