像是雖然可以靠暫停執行緒的方式去控制平均流量,但一般來說除非是一個 byte 一個 byte 接收或傳送
否則通常很難剛好跑到指定的流量時就讓它暫時停止。
然後這時就會有一些相關的衍生問題,例如這一秒多傳的 byte 數目,下一秒是不是要扣回來?是不是需要控制瞬間最大流量?
在 [1] 的討論中,有提到基本的流量控制的程式碼,同時也有人提到「Token Bucket Algorithm」這個演算法
比較詳細的說明可以參考 [2],不過我也沒有認真看這個演算法的內容....
[3] 則是在 Java 上實作 Token Bucket Algorithm 的 Open Source Library~!
使用方法如同 [3] 的說明一樣,相當簡單。
基本的用法如下:(轉錄自 [3] 的說明)
1 2 3 4 5 6 7 8 9 10 11 12 |
// Create a token bucket with a capacity of 40 kb tokens that refills at a fixed interval of 20 kb tokens per second TokenBucket bucket = TokenBuckets.newFixedIntervalRefill( 40960 , 20480 , 1 , TimeUnit.SECONDS); // ... while ( true ) { String response = prepareResponse(); // Consume tokens from the bucket commensurate with the size of the response bucket.consume(response.length()); send(response); } |
然後每次讀資料時,就告訴 Token bucket 讀了多少,其他事情它就會自動處理好了。
在我的狀況中,我要用來處理 InputStream,因此我的實作方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
public class LimitedInputStream extends InputStream { private InputStream STREAM = null ; private TokenBucket BUCKET = null ; public LimitedInputStream (InputStream stream) { this .STREAM = stream; // Initiate the bandwidth limitation. long burst = 20480 ; long avg = 10240 ; this .BUCKET = TokenBuckets.newFixedIntervalRefill(burst, avg, 1 , TimeUnit.SECONDS); } @Override public int read() throws IOException { int len = this .STREAM.read(); if (len > 0 ) { this .BUCKET.consume(len); } return len; } @Override public int read( byte [] buffer) throws IOException { int len = this .STREAM.read(buffer); if (len > 0 ) { this .BUCKET.consume(len); } return len; } @Override public int read( byte b[], int off, int len) throws IOException { len = this .STREAM.read(b, off, len); if (len > 0 ) { this .BUCKET.consume(len); } return len; } } |
它做的事情就是初始化時,順便初始化一個 Token bucket,然後每次讀取 InputStream 時都去更新 Token bucket,更新完才把讀取的長度回應。
平常使用時,唯一需要特別變更的也就只有第 9 和第 10 行,要指定每秒允許的平均流量和瞬間最大流量。
參考資料:
1、How can I limit bandwidth in Java?
2、What do you understand by Token Bucket Algorithm. What are its applications ?
3、token-bucket
1 則留言:
想問 user 要使用你的 class的範例?
張貼留言