2013-03-28 146 views
0

我要實現的限制算法,以避免達到通過我與交互的服務強加的吞吐量限制。吞吐量措施

該限制被指定爲«N個請求1天»其中N是10^6量級的。

我有客戶與服務交互所以他們應該分享測量的分佈式系統。

一個確切的解決方案應包括記錄所有事件,比調用服務的事件«時»計算極限發生:當然,這種做法是過於昂貴,所以我在尋找一個近似解。

我設計的第一個意味着要對事件的檢測進行離散化:例如最多維護24個計數器並記錄一個小時內發生的請求數量。

可接受。

但我覺得更優雅,即使含鉛不同«力»,是下傾的方式連續。

比方說,記錄的最後N個事件,我可以很容易地推斷«當前»吞吐量。當然,這個算法會因爲忽略了幾個小時前發生的過去事件而受到影響。我可以改善老齡化算法,但......和下​​面就跟隨我的問題:

問:«有與和事件的高率估計服務的吞吐量較長期的問題,一個優雅的近似解?»

+0

您的客戶是通過中心點還是他們都直接與有限的服務對話? – James 2013-03-28 10:48:14

+0

超過限制時的行爲是什麼?你只需要監視或限制客戶的速度? – James 2013-03-28 10:49:23

+0

當然,講話者集中在一個適用客戶使用的通用組件中。達到限制時,只需使用OVER_QUOTA錯誤消息忽略所有調用。 – 2013-03-28 11:54:18

回答

0

根據我的意見,你應該使用一個監視器,並讓它每隔15分鐘採樣一次值,以便對請求數量進行合理的猜測。

我嘲笑這裏的東西,但沒有測試過,應該給你一個首發。

import java.util.LinkedList; 
import java.util.Queue; 
import java.util.Timer; 
import java.util.TimerTask; 

public class TestCounter { 

private final Monitor monitor; 

private TestCounter() { 
    monitor = new Monitor(); 
} 

/** The thing you are limiting */ 
public void myService() { 
    if (monitor.isThresholdExceeded()) { 
     //Return error 
    } else { 
     monitor.incremenetCounter(); 
     //do stuff 
    } 
} 

public static void main(String[] args) { 
    TestCounter t = new TestCounter(); 
    for (int i = 0; i < 100000; i++) { 
     t.myService(); 
    } 

    for (int i = 0; i < 100000; i++) { 
     t.myService(); 
    } 
} 

private class Monitor { 
    private final Queue<Integer> queue = new LinkedList<Integer>(); 

    private int counter = 1; 

    /** Number of 15 minute periods in a day. */ 
    private final int numberOfSamples = 76; 

    private final int threshold = 1000000; 

    private boolean thresholdExceeded; 

    public Monitor() { 
     //Schedule a sample every 15 minutes. 
     Timer t = new Timer(); 
     t.scheduleAtFixedRate(new TimerTask() { 
      @Override 
      public void run() { 
       sampleCounter(); 
      } 
     }, 0l, 900000 /** ms in 15 minutes */ 
     ); 
    } 

    /** Could synchroinise */ 
    void incremenetCounter() { 
     counter++; 
    } 

    /** Could synchroinise */ 
    void sampleCounter() { 
     int tempCount = counter; 
     counter = 0; 
     queue.add(tempCount); 

     if (queue.size() > numberOfSamples) { 
      queue.poll(); 
     } 

     int totalCount = 0; 
     for (Integer value : queue) { 
      totalCount += value; 
     } 
     if (totalCount > threshold) { 
      thresholdExceeded = true; 
     } else { 
      thresholdExceeded = false; 
     } 
    } 

    public boolean isThresholdExceeded() { 
     return thresholdExceeded; 
    } 
} 
}