簡體   English   中英

限制請求的速率限制算法

[英]Rate limiting algorithm for throttling request

我需要為限制請求設計一個速率限制器服務。 對於每個傳入請求,方法將檢查每秒請求是否超過其限制。 如果已超過,則返回等待處理所需的時間。

尋找一個簡單的解決方案,它只使用系統滴答計數和rps(每秒請求數)。 不應使用隊列或復雜的速率限制算法和數據結構。

編輯:我將在c ++中實現它。 另外,請注意我不想使用任何數據結構來存儲當前正在執行的請求。 API就像:

if(!RateLimiter.Limit()){do work RateLimiter.Done();

否則拒絕請求

用於此的最常見算法是令牌桶 沒有必要發明新東西,只需搜索您的技術/語言的實現。

如果您的應用程序具有高可用性/負載平衡性,您可能希望將存儲桶信息保留在某種持久性存儲上。 Redis是一個很好的候選人。

我寫的Limitd是一種不同的方法,是限制的守護進程。 如果流量符合要求,應用程序會使用限制客戶端詢問守護程序。 限制在限制服務器上配置,應用程序與算法無關。

因為你沒有給出任何語言或平台的暗示,我只會給出一些偽代碼。

你需要的東西

  • 當前執行請求的列表
  • 等待通知請求完成的地方

代碼可以很簡單

var ListOfCurrentRequests; //A list of the start time of current requests
var MaxAmoutOfRequests;// just a limit
var AverageExecutionTime;//if the execution time is non deterministic the best we can do is have a average

//for each request ether execute or return the PROBABLE amount to wait
function OnNewRequest(Identifier)
{
    if(count(ListOfCurrentRequests) < MaxAmoutOfRequests)//if we have room 
    {
        Struct Tracker
        Tracker.Request = Identifier;
        Tracker.StartTime = Now; // save the start time
        AddToList(Tracker) //add to list
    }
    else
    {
        return CalculateWaitTime()//return the PROBABLE time it will take for a 'slot' to be available
    }
}
//when request as ended release a 'slot' and update the average execution time
function OnRequestEnd(Identifier)
{
    Tracker = RemoveFromList(Identifier);
    UpdateAverageExecutionTime(Now - Tracker.StartTime);
}

function CalculateWaitTime()
{
    //the one that started first is PROBABLY the first to finish
    Tracker = GetTheOneThatIsRunnigTheLongest(ListOfCurrentRequests);
    //assume the it will finish in avg time
    ProbableTimeToFinish = AverageExecutionTime - Tracker.StartTime;
    return ProbableTimeToFinish
}

但請記住,這有幾個問題

  • 假設通過返回等待時間,客戶端將在傳遞的時間之后發出新請求。 由於時間是一個估計,你不能用它來延遲執行,或者你仍然可以溢出系統
  • 由於您沒有保留隊列並延遲請求,因此客戶可以等待他需要的更多時間。
  • 最后,因為你沒有保留隊列,優先考慮和延遲請求,這意味着你可以有一個實時鎖定 ,你告訴客戶稍后返回,但當他返回某人已經取得了它的位置,他必須再次回來。

所以理想的解決方案應該是一個實際的執行隊列,但是因為你不想要一個...我想這是下一個最好的事情。

根據你的評論你只是一個簡單的(不是非常精確的)每秒請求標志。 在這種情況下,代碼可以是這樣的

var CurrentRequestCount;
var MaxAmoutOfRequests;
var CurrentTimestampWithPrecisionToSeconds
function CanRun()
{
    if(Now.AsSeconds > CurrentTimestampWithPrecisionToSeconds)//second as passed reset counter
        CurrentRequestCount=0;

    if(CurrentRequestCount>=MaxAmoutOfRequests)
        return false;

    CurrentRequestCount++
    return true;
}

似乎不是一個非常可靠的方法來控制什么..但..我相信這是你問的..

暫無
暫無

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

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