Мера пропускной способности

Я должен реализовать алгоритм ограничения, чтобы избежать ограничения пропускной способности, налагаемого службой, с которой я взаимодействую.

Предел указывается как "N запросов за 1 день", где N порядка 10^6.

У меня есть распределенная система клиентов, взаимодействующих с сервисом, поэтому они должны разделять измерения.

Точное решение должно включать запись всех событий, а затем вычисление предела "когда" происходит событие вызова службы: конечно, этот подход слишком дорог, и поэтому я ищу приблизительное решение.

Первый, который я разработал, подразумевает дискретизацию обнаружения событий: например, поддержание максимум 24 счетчиков и запись количества запросов, произошедших в течение часа.

Приемлемый.

Но я чувствую, что более элегантным, хотя и ведомым разными "силами", является отклонение подхода от континуума.

Допустим, записывая последние N событий, я мог легко вывести "текущую" пропускную способность. Конечно, этот алгоритм страдает из-за отсутствия учета прошлых событий, произошедших часами ранее. Я мог бы улучшить с помощью алгоритма старения, но... и вот мой вопрос:

Вопрос: "Существует элегантное приблизительное решение проблемы оценки пропускной способности услуги в течение длительного периода при высокой частоте событий?"

1 ответ

Согласно моим комментариям, вы должны использовать монитор и каждые 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;
    }
}
}
Другие вопросы по тегам