簡體   English   中英

令牌桶算法,限速javascript?

[英]token bucket algorithm, rate limiting javascript?

我正在嘗試編寫一個算法來防止在8秒內發送超過5條消息,我在python中找到了令牌桶算法的公式,所以我試圖用javascript實現它,但我錯過了一件事。

last_check變量對我來說並不清楚。 如果我在一分鍾內跟蹤60秒,問題是在第59秒后它重新循環,數學被拋棄。

第一次迭代

如果last_check = new Date().getSeconds()讓我們說它在跟蹤的那一刻是33秒,我們現在比較33秒。

rateLimit()函數執行時,它獲取調用它的current時間,例如消息, current new Date().getSeconds()是40秒,例如.... last_check后7秒

所以time_passed現在是7秒, last_checked變成40。

津貼結果

allowance7 * (5.0/8.0) = 4.375


問題出在哪里

如果last_checked保持在40,並且22秒通過直到新消息,則下面的第二次迭代的公式變為。

第二次迭代

current變為2(40 + 22) new Date().getSeconds()循環回到2 ... time_passed現在是(2-40)= -38秒, last_checked現在是2。

津貼結果


allowance值為-38 * (5.0/8.0) = -23.75

var rate = 5.0; // unit: messages
var per = 8.0; // unit: seconds
var allowance = rate; // unit: messages
var last_check = new Date().getSeconds();

function rateLimit() {
    current = new Date().getSeconds(); // floating-point, e.g. usec accuracy. Unit: seconds
    time_passed = current - last_check;
    last_check = current;
    allowance += time_passed * (rate / per);

    console.log('Current time: ' + current);
    console.log('Time passed: ' + time_passed);
    console.log('Last check: ' + last_check);
    console.log('Allowance: ' + allowance);

    if (allowance > rate) {
        allowance = rate; // throttle
        console.log('throttle');
    }
    if (allowance < 1.0) {
        console.log('discard message');
        return false;
    } else {
        allowance -= 1.0;
        console.log('forward message');
        return true;
    }
}

http://jsfiddle.net/wxjfcm5d/47/

我同意@ Evilzebra的評論,即解決方案可能有點復雜。 根據您所需的行為,我以這種方式實現它:

var ii = 0;
var perMils = per * 1000;
function rateLimit() {
    if (ii <= rate) {
        ++ii;
        setTimeout(function() {--ii;}, perMils);
        return true;
    }
    return false;
}

current - last_check ,您需要兩個日期之間的差異,而不是秒針的位置之間的差異。

new Date().getSeconds()替換new Date().getSeconds() new Date().getTime()/1000 (或new Date().getTime()但你必須用var per = 8000.0替換var per = 8.0 )。

這將導致current - last_check始終為正數秒(或毫秒),而不是當秒數翻轉到分鍾時為負數。

您也可以使用我寫過的防洪庫。 它使用令牌桶算法

用法

import FloodProtection from 'flood-protection';

const floodProtection = new FloodProtection({
    rate: 5, 
    // default: 5, unit: messages
    // IMPORTANT: rate must be >= 1 (greater than or equal to 1)

    per: 8, 
    // default: 8, unit: seconds
});

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM