0

対話しているサービスによって課されるスループット制限に達するのを避けるために、制限アルゴリズムを実装する必要があります。

制限は «1 日に N リクエスト» として指定されます。ここで、N は 10^6 の大きさのオーダーです。

サービスと対話するクライアントの分散システムがあるため、測定値を共有する必要があります。

正確な解決策には、すべてのイベントを記録し、サービスを呼び出すイベントが発生したときの制限を計算する必要があります。もちろん、このアプローチはコストがかかりすぎるため、おおよその解決策を探しています。

私が考案した最初のものは、イベントの検出を離散化することを暗示しています。たとえば、最大 24 のカウンターを維持し、1 時間以内に発生したリクエストの数を記録します。

許容できる。

しかし、たとえ別の「力」に導かれたとしても、より洗練された方法は、連続体へのアプローチを拒否することだと思います.

最後の N 個のイベントを記録すると、«現在の» スループットを簡単に推測できるとしましょう。もちろん、このアルゴリズムは、数時間前に発生した過去のイベントを考慮していないために問題があります。エージング アルゴリズムを使用して改善することはできますが、ここで私の質問に従います。

Q: «イベントの発生率が高く、長期間にわたるサービスのスループットを見積もる問題に、洗練されたおおよその解決策はありますか?»

4

1 に答える 1

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;
    }
}
}
于 2013-03-28T14:08:30.847 に答える