Могу ли я обрабатывать запросы, сделанные распределенным приложением?

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

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

Теперь мы переносимся с одного сервера на кластер, поэтому есть две копии приложения.

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

Это среда JavaEE 5. Каков наилучший способ дросселировать запросы, отправляемые приложением?

Ответ 1

Поскольку вы уже находитесь в среде Java EE, вы можете создать MDB, который обрабатывает все запросы к веб-сервису на основе очереди JMS. Экземпляры приложения могут просто отправлять свои запросы в очередь, и MDB получит их и вызовет веб-сервис.

На самом деле очередь может быть сконфигурирована с соответствующим количеством сеансов, что ограничит параллельный доступ к вам webservice, таким образом, ваше управление регулируется через конфигурацию очереди.

Результаты могут быть возвращены через другую очередь (или даже очередь на экземпляр приложения).

Ответ 2

Я рекомендую использовать beanstalkd, чтобы периодически накачивать коллекцию запросов (заданий) в трубку ( очередь), каждая с соответствующей задержкой. Любое количество "рабочих" потоков или процессов будет ждать, когда будет доступен следующий запрос, и если работник закончит раньше, он может выбрать следующий запрос. С другой стороны, нет никакой явной балансировки нагрузки между рабочими, но я обнаружил, что распределение запросов из очереди было хорошо сбалансировано.

Ответ 3

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

Как только приложение исчерпает свои токены, оно должно попросить еще немного, прежде чем снова ударить веб-службу.

Конечно, это все усложняется, когда есть требования в отношении времени каждого вызова, которое каждое приложение делает из-за concurrency к веб-службе.

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

Ответ 4

Узлы N должны связываться. Существуют различные стратегии:

  • : каждый node будет транслировать всем остальным, что он макетирует вызов, и все остальные узлы учитывают это. Узлы равны и поддерживают индивидуальный глобальный счет (каждый node знает обо всех других вызовах node).
  • master node: один node является специальным, его мастер и все остальные узлы запрашивают разрешение у мастера перед выполнением вызова. Мастер - единственный, кто знает глобальный счет.
  • выделенный мастер: то же самое, что и master, но "мастер" не выполняет вызовы на itslef, это просто служба, которая отслеживает вызовы.

В зависимости от того, насколько вы ожидаете масштабирования в будущем, одна или другая стратегия может быть лучше. Для 2-х узлов самый простой из них транслируется, но по мере увеличения количества узлов проблемы начинают монтироваться (вы будете тратить больше времени на трансляцию и отвечать на широковещательные передачи, чем на самом деле делать WS-запросы).

Как взаимодействуют узлы, зависит от вас. Вы можете открыть TCP-канал, вы можете широковещать UDP, вы можете сделать полноценный WS только для этой цели, вы можете использовать протокол общего доступа к файлам. Независимо от того, что вы делаете, вы больше не находитесь в процессе, поэтому применимы все заблуждения распределенных вычислений.

Ответ 5

Это интересная проблема, и трудность решения зависит от степени строгости того, насколько вы хотите быть на дросселировании.

Мое обычное решение для этого - JBossCache, отчасти потому, что оно поставляется в комплекте с JBoss AppServer, но также потому, что оно обрабатывает задачу скорее Что ж. Вы можете использовать его как своего рода распределенный хэш, записывая статистику использования с разной степенью детализации. Обновления для него могут выполняться асинхронно, поэтому это не замедляет работу.

JBossCache обычно используется для высокопроизводительного распределенного кэширования, но я предпочитаю его также для работы с более легкими весами. Это чистая java, и не требует никаких проблем с JVM (в отличие от Terracotta).

Ответ 6

Hystrix был разработан для практически точного сценария, который вы описываете. Вы можете определить размер пула потоков для каждой службы, чтобы у вас было задано максимальное количество одновременных запросов, и он ставит в очередь запросы, когда пул заполнен. Вы также можете определить тайм-аут для каждой службы и когда служба начнет превышать свой тайм-аут, Hystrix будет отклонять дальнейшие запросы к этой услуге в течение короткого периода времени, чтобы дать услуге возможность вернуться на ноги. Там также мониторинг в реальном времени всего кластера через Turbine.