シーン
1. 第三者からの制御されない呼び出しによってシステムがダウンするのを防ぐために、重要なリクエストのフローを制限する必要があります。
2. サービス プロバイダーには、呼び出すインターフェイスに対して 1 分あたりのフロー制限があります。
シナリオ 1 は通常、比較的成熟したフレームワークによってサポートされており、alibaba Sentinel や Spring clound hystrix などの電流制限メカニズムをシステムに導入するための単純な構成のみが必要です。
シナリオ 2: サービス プロバイダーがフローを制限する サービスの結果を正しく取得するには、リクエストのフローも制限する必要があります。
いくつかの一般的な電流制限スキーム
カウント電流制限、固定ウィンドウ、スライディング ウィンドウ、リーキー バケット アルゴリズム、トークン バケット
最も簡単な解決策
上記の電流制限アルゴリズムではなく、相手が制限しているのでリクエストを続ければよく、リクエスト結果が制限リクエストであれば、一定時間スリープしてリクエストを継続します。
public class WeTask{
public static void main(String[] args) {
// 伪代码
task(1);
}
public Static void task(int para) {
Boolean res = getResponse();
if (!res) {
//限流了
Thread.sleep(1000);
// 继续发起上次请求
task(para);
}
// 处理结果
dosomething()
}
}
トークンバケットはセマフォを通じて実装されます
私たちは自分自身のリクエストを制限し、相手は結果を制限するため、トークン バケットを使用して、相手から与えられた 1 分あたり 300 リクエストの制限に基づいてリクエストを制御します。
コードでは多くの詳細が省略されていますが、主にセマフォがトークン バケットを実装し、取得メソッドと解放メソッドを使用してフェッチしてバケットに入れる方法を理解するためです。
public class WeTask{
@autowire
Semaphore apiSemaphore;
@Bean(name = "apiSemaphore")
public Semaphore apiSemaphore() {
Semaphore apiSemaphore = new Semaphore(40, true);
scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
try {
// 每10s往桶里放允许的请求数
log.info("release ...40");
apiSemaphore.release(40);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}, -1, 10, TimeUnit.SECONDS);
return apiSemaphore;
}
public static void main(String[] args) {
// 伪代码
task(1);
}
public Static void task(int para) {
apiSemaphore.acquire();
Boolean res = getResponse();
//伪代码 还要再次判断可能限流(不信任原则,对方可能会调整限流量)
// 处理结果
dosomething()
}
}
関連する API
selectedThreadPoolExecutor: スケジュールされたタスクのスレッド プールはタイマーに似ていますが、タイマーよりも強力で、マルチスレッドのスケジュールされたタスクをサポートします。
セマフォ: セマフォ、AQS を実装するための内部クラス継承、公平なロックと不公平なロックをサポート
その他の関連知識については、前の記事「フェンスとロック」を参照してください。
https://blog.csdn.net/u013565163/article/details/87310700