passshift
@passshift
php, js, html5, css

Как ограничить частоту запросов к бэкэнду?

Здравствуйте!

Выполняю запрос каждые 10000 мс:
setInterval(load, 10000);

Он подгружает определенную информацию в див, информация берется из серверной БД.

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

Подскажите, можно как-то защититься от этого?

Вот собственно запрос к БД :

return DB::select('messages.user_id', 'message', 'messages.date', 'username', 'small_avatar')
                        ->from('messages')
                        ->join('users', 'LEFT')
                        ->on('messages.user_id', '=', 'users.id')
                        ->join('users_details', 'LEFT')
                        ->on('messages.user_id', '=', 'users_details.user_id')
                        ->order_by('messages.id')
                        ->where('date', '>', Date::nowToDB("now - 3 minutes"))
                        ->execute()
                        ->as_array();


- Берет посты, авторов этих постов и информацию о них (из users_details), выводятся посты которые старше 3 минут... сам запрос не очень то и простой хотя бы потому что данные берутся аж из трех таблиц...

Кэширование и так включено...
  • Вопрос задан
  • 312 просмотров
Пригласить эксперта
Ответы на вопрос 6
dom1n1k
@dom1n1k
Кэшировать результаты запроса к базе на ~5 секунд?
А скорее даже не результат запроса, а прямо конечный xml/html/json, который потом отсылается на клиент.
То есть в пределах 5 секунд сервер отдает один и тот же ответ.
Ответ написан
Staltec
@Staltec
Node.js разработчик
Если данные не персонализированы, то можно кэшировать результаты на стороне сервера в Redis и обновлять их там с определённой периодичностью. Таким образом, частые обновления конечно будут загружать сервер, но несущественно и не будут досить обращение к базе данных. Если данные персонализированы и у вас много памяти или мало активных подключений, то тоже можно кэшировать в Redis.

Также имеет смысл рассмотреть вопрос использования websocket (с полифилами для старых браузеров). Тогда активный клиент будет просто держать сокет, а периодическую рассылку данных будет инициировать сервер.
Ответ написан
Комментировать
На выбор:
* На стороне пыхи: сохранять в сессию microtime успешно обработанного запроса. В начале обработки запроса проверять: если текущий microtime меньше, чем сохранённый в сессию плюс 10, то вернуть код 403 и не обрабатывать запрос дальше.
* В nginx'е можно настроить request rate.
* Оптимизировать код (оптимизировать запросы, кеширование, оптимизация самого кода,..) с тем, чтобы не вводить искусственных ограничений на request rate.
Ответ написан
UZEIR
@UZEIR
Учусь. Пытаюсь развиваться.
Все, что делается на стороне клиента, это не безопасно, да есть способы зашифровать данные. Но это лишь не много усложнит задачу не более. Почему бы просто не поставить крон?
Ответ написан
sergiks
@sergiks Куратор тега PHP
♬♬
Выдавать и проверять токен. При первой загрузке страницы выдаётся уникальный токен, с которым может быть выполнен первый запрос к апи. В ответ на первый запрос с токеном отдаются данные и токен для следующего запроса – только с ним, и не раньше X секунд можно получить данные. И так далее.

Разумеется, хранить токены в in-memory хранилище (Redis, Memcached, APC). Продумать вариант с потерей связи и перезапросом со старым токеном (кэшировать данные на N секунд). Запрос со следующим токеном стирает из кэша предыдущий и его данные.
Ответ написан
Комментировать
samizdam
@samizdam
Посмотрите в сторону WebSocket - в общем случае это как раз и является решением: сервер будет уведомлять клиент с нужным ему интервалом, а клиент - пассивно ждать обновлений.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы