吞吐量测量

时间:2013-03-28 10:44:22

标签: traffic-measurement

我必须实施限制算法,以避免达到我正在与之交互的服务所施加的吞吐量限制。

该限制被指定为“超过1天的N次请求”,其中N的数量级为10 ^ 6.

我有一个与服务交互的分布式客户系统,因此他们应该共享该措施。

一个确切的解决方案应该包括记录所有事件,而不是计算限制«何时»调用服务的事件发生:当然这种方法太昂贵,所以我正在寻找一个近似的解决方案。

我设计的第一个暗示要对事件的检测进行离散化:例如,最多维护24个计数器并记录一小时内发生的请求数。

可接受。

但我觉得更优雅,即使是由不同的“力量”引导,也是为了使连续统一的方法变得更加明确。

假设记录最后N个事件,我可以很容易地推断出“当前”吞吐量。当然,该算法因缺少对前几小时发生的过去事件的考虑而受到损害。我可以使用老化算法进行改进但是...并且在这里遵循我的问题:

问:«对于长期估计服务吞吐量和事件发生率高的问题,有一个优雅的近似解决方案吗?»

1 个答案:

答案 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;
    }
}
}