token bucketアルゴリズムの実現について話します
3287 ワード
シーケンス
本文は主にtoken bucketアルゴリズムの実現を研究する.
ストリーム制限アルゴリズムの概要
主に次のようなものがあります.信号量Semaphore に基づく
数量次元のみ、時間次元なし fixed window に基づく
時間次元を持っていますが、2つのウィンドウの臨界点で制限フローを超えた場合が発生しやすいです.たとえば、1分に10個のリクエストを制限し、00:59に10回、01:01に10回、00:30-01:30というウィンドウでは、この分に20回リクエストしましたが、コントロールできませんでした. rolling window に基づく
fixed windowで解決されていないウィンドウの臨界問題を解決するには、主にtoken bucketベースのアルゴリズムとleaky bucketベースのアルゴリズムがある.
token bucketアルゴリズム token bucketに指定されたレートで に追加一つのbucketはその容量制限があり、その容量を超えると余分なtokenは に破棄される.要求が来ると、まずtokenを取得しようとするが、残りのtokenが十分であれば放行し、足りなければ放行( は許されない.
単純な実装以上はbucket 4 jが与える簡単な実装であり、token bucketアルゴリズム を理解するために使用される.このアルゴリズムはスレッドを採用してrefill tokenに行かなかった.bucketが多すぎると、スレッドが多すぎて、cpu を消費するからだ.このアルゴリズムはperiodごとに使用されるtokenを格納せず、充填が必要なtoken を計算するためにlastRefillTimestampフィールドを設計した. tryConsumerのたびにメソッド内部でまずrefillが呼び出され、設定された速度および時間差からこの時間帯に補足が必要なtokenを計算し、availableTokensおよびlastRefillTimestamp を更新する以降のストリーム制限判定は、availableTokensと要求numberTokens とを判定する.
小結
token bucketアルゴリズムは、qpsに基づいてストリームを制限し、その簡単な実現は、単位時間でtokenのレートを補充し、tryConsumerのたびにレートに基づいてavailableTokensを修正することである.
doc Brief overview of token-bucket algorithm
本文は主にtoken bucketアルゴリズムの実現を研究する.
ストリーム制限アルゴリズムの概要
主に次のようなものがあります.
数量次元のみ、時間次元なし
時間次元を持っていますが、2つのウィンドウの臨界点で制限フローを超えた場合が発生しやすいです.たとえば、1分に10個のリクエストを制限し、00:59に10回、01:01に10回、00:30-01:30というウィンドウでは、この分に20回リクエストしましたが、コントロールできませんでした.
fixed windowで解決されていないウィンドウの臨界問題を解決するには、主にtoken bucketベースのアルゴリズムとleaky bucketベースのアルゴリズムがある.
token bucketアルゴリズム
token
)単純な実装
/**
* The minimalistic token-bucket implementation
*/
public class MinimalisticTokenBucket {
private final long capacity;
private final double refillTokensPerOneMillis;
private double availableTokens;
private long lastRefillTimestamp;
/**
* Creates token-bucket with specified capacity and refill rate equals to refillTokens/refillPeriodMillis
*/
public MinimalisticTokenBucket(long capacity, long refillTokens, long refillPeriodMillis) {
this.capacity = capacity;
this.refillTokensPerOneMillis = (double) refillTokens / (double) refillPeriodMillis;
this.availableTokens = capacity;
this.lastRefillTimestamp = System.currentTimeMillis();
}
synchronized public boolean tryConsume(int numberTokens) {
refill();
if (availableTokens < numberTokens) {
return false;
} else {
availableTokens -= numberTokens;
return true;
}
}
private void refill() {
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis > lastRefillTimestamp) {
long millisSinceLastRefill = currentTimeMillis - lastRefillTimestamp;
double refill = millisSinceLastRefill * refillTokensPerOneMillis;
this.availableTokens = Math.min(capacity, availableTokens + refill);
this.lastRefillTimestamp = currentTimeMillis;
}
}
private static final class Selftest {
public static void main(String[] args) {
// 100 tokens per 1 second
MinimalisticTokenBucket limiter = new MinimalisticTokenBucket(100, 100, 1000);
long startMillis = System.currentTimeMillis();
long consumed = 0;
while (System.currentTimeMillis() - startMillis < 10000) {
if (limiter.tryConsume(1)) {
consumed++;
}
}
System.out.println(consumed);
}
}
}
小結
token bucketアルゴリズムは、qpsに基づいてストリームを制限し、その簡単な実現は、単位時間でtokenのレートを補充し、tryConsumerのたびにレートに基づいてavailableTokensを修正することである.
doc