Подтвердить что ты не робот

Как реализовать ограничение скорости на основе токена клиента в Spring?

Я разрабатываю простой REST API, используя Spring 3 + Spring MVC. Аутентификация будет выполняться через OAuth 2.0 или basic auth с помощью токена клиента с помощью Spring Security. Это все еще обсуждается. Все соединения будут принудительно подключены через SSL-соединение.

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

Например, если есть три сервера api, A, B, C и клиенты ограничены 5 запросами в секунду, то клиент, который делает 6 запросов, как это, найдет запрос на C, отклоненный с ошибкой.

A recieves 3 requests   \
B receives 2 requests    | Executed in order, all requests from one client.
C receives 1 request    /

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

Настройка будет представлять собой несколько (2-5) веб-серверов за балансировщиком HAProxy. Существует Cassandra, и memcached используется. Веб-серверы будут работать на Jetty.

Одним из возможных решений может быть создание настраиваемого фильтра безопасности Spring, который извлекает токен и проверяет, сколько запросов было выполнено с ним за последние X секунд. Это позволило бы нам сделать некоторые вещи, как разные лимиты ставок для разных клиентов.

Любые предложения о том, как это можно сделать? Есть ли существующее решение или мне придется написать собственное решение? Раньше я не делал много инфраструктуры веб-сайта.

4b9b3361

Ответ 1

Я бы не стал модифицировать код уровня приложения для удовлетворения этого требования, если это вообще возможно.

Я просмотрел HAProxy. Документация LB здесь не слишком очевидна, но это требование может потребовать полного изучения ACL.

Включение HAProxy в одну сторону, возможная архитектура заключается в том, чтобы вывести Apache WebServer спереди и использовать плагин Apache для ограничения скорости. Запросы с превышением лимита отклонены, а серверы приложений в уровне за Apache затем отделены от ограничений по скорости, что упрощает их. Вы также можете использовать статический контент с веб-сервера.

См. ответ на этот вопрос Как я могу реализовать ограничение скорости с помощью Apache? (запросы в секунду)

Надеюсь, это поможет. Rob

Ответ 2

Вы могли бы установить лимиты ставок в разных точках потока (как правило, чем выше, тем лучше), а общий подход, который у вас есть, имеет большой смысл. Одним из вариантов реализации является использование 3scale для этого (http://www.3scale.net) - он ограничивает лимиты, аналитику, управление ключами и т.д. И работает либо с плагином кода (плагин Java здесь: https://github.com/3scale/3scale_ws_api_for_java), который толкает или помещает что-то вроде Varnish (http://www. varnish-cache.org) в соответствии с действующими ограничениями.

Ответ 4

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

В моем приложении я использую "session_id" для идентификации клиента запроса. Затем создайте фильтр сервлета или spring HandlerInterceptorAdapter, чтобы отфильтровать запрос, затем проверьте "session_id" на репозиторий данных с центральным управлением, который может быть memcached, redis, cassandra или zookeeper.