Как реализовать распределенный ограничитель скорости?

Скажем, у меня есть P процессов, выполняющих некоторую бизнес-логику на N физических машинах. Эти процессы вызывают, скажем, какой-нибудь веб-сервис S. Я хочу убедиться, что не более X вызовов службы S в секунду всеми процессами P вместе взятыми.

Как можно реализовать такое решение?

Ограничитель скорости Google Guava хорошо работает для процессов, работающих на одном устройстве, но не в распределенной настройке.

Существуют ли стандартные, готовые к использованию решения для JAVA? [может быть основано на зоопарке]

Спасибо!


person Dhrumil Upadhyaya    schedule 19.07.2015    source источник
comment
Куратор (обычно используемый клиент Java ZooKeeper) не имеет точного рецепта. Однако у Curator есть рецепт Distributed Long, который можно использовать в качестве основы для этого: curator.apache.org/curator-recipes/distributed-atomic-long.html   -  person Randgalt    schedule 19.07.2015
comment
Хм, разве общий семафор не подходит для этого случая? curator.apache.org/curator-recipes/shared-semaphore.html   -  person Oleg Komarov    schedule 20.07.2015
comment
Проблема с общим семафором заключается в том, что есть кто-то, кто выпускает все блокировки каждую секунду. Я думаю, что распределенный атомарный длинный или целочисленный будет подходящим, но я еще не реализовал свое решение.. так что не уверен   -  person Dhrumil Upadhyaya    schedule 20.07.2015
comment
Как насчет того, чтобы позволить вашим процессам запускать столько запросов к вашей веб-службе, сколько они хотят, но сбалансировать нагрузку на ваш доступ к этой службе через шлюз веб-службы, такой как Spring Cloud?   -  person Fritz Duchardt    schedule 22.07.2015


Ответы (3)


Bucket4j — это java-реализация алгоритма ограничения скорости "token-bucket". Работает как локально, так и распределенно (поверх JCache). Для распределенного варианта использования вы можете выбрать любую реализацию JCache, например Hazelcast или Apache Ignite. См. этот пример использования Bucket4j в кластере.

person Bukhtoyarov Vladimir    schedule 28.04.2017

Я работал над решением с открытым исходным кодом для таких проблем.

Limited — это «сервер» для лимитов. Ограничения реализуются с помощью алгоритма Token Bucket.

В основном вы определяете ограничения в конфигурации службы следующим образом:

buckets:
  "request to service a":
     per_minute: 10
  "request to service b":
     per_minute: 5

Служба запускается как демон, прослушивающий порт TCP/IP.

Затем ваше приложение делает что-то в этом роде:

var limitd = new Limitd('limitd://my-limitd-address');

limitd.take('request to service a', 'app1' 1, function (err, result) {
  if (result.conformant) {
    console.log('everything is okay - this should be allowed');
  } else {
    console.error('too many calls to this thing');
  }
});

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

Сервер включен:

https://github.com/auth0/limitd

Мы планируем работать над несколькими SDK, но пока у нас есть только node.js и частично реализованный go:

https://github.com/limitd

person José F. Romaniello    schedule 23.07.2015
comment
Просто любопытно, а как вы HA ваш сервер с ограниченной доступностью, разве вам не пришлось бы делиться состоянием между вашей настройкой с ограниченной HA.? - person user432024; 27.06.2019

https://github.com/jdwyah/ratelimit-java обеспечивает распределенные ограничения скорости, которые должны просто это. Вы можете настроить свой лимит как S в секунду/минуту и ​​т. д. и выбрать размер пакета/скорость пополнения дырявого ведра, которое находится под крышками.

person jdwyah    schedule 20.02.2017