我必须实施限制算法,以避免达到我正在与之交互的服务所施加的吞吐量限制。
该限制被指定为“超过1天的N次请求”,其中N的数量级为10 ^ 6.
我有一个与服务交互的分布式客户系统,因此他们应该共享该措施。
一个确切的解决方案应该包括记录所有事件,而不是计算限制«何时»调用服务的事件发生:当然这种方法太昂贵,所以我正在寻找一个近似的解决方案。
我设计的第一个暗示要对事件的检测进行离散化:例如,最多维护24个计数器并记录一小时内发生的请求数。
可接受。
但我觉得更优雅,即使是由不同的“力量”引导,也是为了使连续统一的方法变得更加明确。
假设记录最后N个事件,我可以很容易地推断出“当前”吞吐量。当然,该算法因缺少对前几小时发生的过去事件的考虑而受到损害。我可以使用老化算法进行改进但是...并且在这里遵循我的问题:
问:«对于长期估计服务吞吐量和事件发生率高的问题,有一个优雅的近似解决方案吗?»
答案 0 :(得分: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;
}
}
}