Мне нужен компонент / класс, который ограничивает выполнение какого-либо метода до максимума M вызовов в N секунд (или мс или нанос, не имеет значения).
Другими словами, мне нужно убедиться, что мой метод выполняется не более M раз в скользящем окне из N секунд.
Если вы не знаете существующий класс, не стесняйтесь размещать свои решения / идеи, как бы вы это реализовали.
java
throttling
vtrubnikov
источник
источник
Ответы:
Я бы использовал кольцевой буфер временных меток с фиксированным размером M. Каждый раз, когда вызывается метод, вы проверяете самую старую запись, и если она меньше N секунд в прошлом, вы выполняете и добавляете другую запись, иначе вы спите для разницы во времени.
источник
То, что работало из коробки для меня, было Google Guava RateLimiter .
источник
tryAquire()
Конкретно, вы должны быть в состоянии реализовать это с помощью
DelayQueue
. Инициализируйте очередьM
Delayed
экземплярами с задержкой, изначально установленной на ноль. Когда поступают запросы к методу,take
токен, который заставляет метод блокироваться, пока не будет выполнено требование регулирования. Когда токен был взят,add
новый токен в очереди с задержкойN
.источник
offer
и возможный рост массива), и все это довольно тяжело для меня. Я думаю, для других это может быть совершенно нормально.Читайте на ведро Token алгоритме . По сути, у вас есть ведро с жетонами. Каждый раз, когда вы выполняете метод, вы берете токен. Если токенов больше нет, вы блокируете их, пока не получите. Между тем, существует некоторый внешний субъект, который пополняет токены с фиксированным интервалом.
Я не знаю библиотеки для этого (или чего-то подобного). Вы можете написать эту логику в своем коде или использовать AspectJ для добавления поведения.
источник
Если вам нужен ограничитель скорости скользящего окна на основе Java, который будет работать в распределенной системе, вы можете взглянуть на проект https://github.com/mokies/ratelimitj .
Конфигурация с поддержкой Redis, ограничивающая количество запросов по IP до 50 в минуту, будет выглядеть так:
См. Https://github.com/mokies/ratelimitj/tree/master/ratelimitj-redis для получения дополнительной информации о конфигурации Redis.
источник
Это зависит от приложения.
Представьте себе случай, когда несколько потоков хотят, чтобы токен выполнял какое-либо глобально ограниченное по скорости действие, при котором пакет не был разрешен (т.е. вы хотите ограничить 10 действий в 10 секунд, но вы не хотите, чтобы 10 действий происходили в первую секунду, а затем оставались 9 секунд остановились).
Недостаток DelayedQueue: порядок, в котором потоки запрашивают токены, может не совпадать с порядком, в котором они получают свой запрос. Если несколько потоков заблокированы в ожидании токена, неясно, какой из них возьмет следующий доступный токен. С моей точки зрения, у вас могут быть темы, ожидающие вечно.
Одним из решений является минимальный интервал времени между двумя последовательными действиями и выполнение действий в том же порядке, в котором они были запрошены.
Вот реализация:
источник
minTime
значит здесь? Что оно делает? Вы можете объяснить это?minTime
минимальное количество времени, которое должно пройти после того, как токен будет израсходован, прежде чем будет использован следующий токен.Хотя это не то, что вы просили,
ThreadPoolExecutor
это может быть полезно для ограничения одновременных запросов M вместо M запросов за N секунд.источник
Я реализовал простой алгоритм регулирования. Попробуйте эту ссылку, http://krishnaprasadas.blogspot.in/2012/05/throttling-algorithm.html
Краткое описание алгоритма,
Этот алгоритм использует возможности Java Delayed Queue . Создайте задержанный объект с ожидаемой задержкой (здесь 1000 / M для миллисекунды TimeUnit ). Поместите тот же объект в отложенную очередь, которая будет интерном для нас. Затем перед каждым вызовом метода возьмите объект из очереди, take является блокирующим вызовом, который будет возвращаться только после указанной задержки, и после вызова метода не забудьте поместить объект в очередь с обновленным временем (здесь текущие миллисекунды) ,
Здесь мы также можем иметь несколько задержанных объектов с различной задержкой. Этот подход также обеспечит высокую пропускную способность.
источник
Моя реализация ниже может обрабатывать произвольную точность времени запроса, она имеет O (1) временную сложность для каждого запроса, не требует никакого дополнительного буфера, например O (1) пространственной сложности, кроме того, он не требует фонового потока для выпуска токена, вместо этого токены выпускаются в соответствии с временем, прошедшим с момента последнего запроса.
источник
Попробуйте использовать этот простой подход:
}
источник
Apache Camel также поддерживает поставляется с механизмом Throttler следующим образом:
источник
Это обновление кода LeakyBucket выше. Это работает для более чем 1000 запросов в секунду.
и unittest для выше:
источник
minTimeNano
значит здесь? Вы можете объяснить?Вот немного продвинутая версия простого ограничителя скорости
И юнит-тесты
источник
Мое решение: простой метод util, вы можете изменить его для создания класса-оболочки.
Взять из JAVA Thread Debounce и Throttle
источник