API-интерфейс отслеживания сервлетов Java - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь создать HTTP API, используя самый простой сервлет j2ee с MySQL.

Требуется ограничить частоту, с которой конкретный пользователь звонит на наш сервер. Скажем, когда я обнаружил, что их предел TPS равен 20, после того, как они сделали 21-й звонок в ту же секунду, мне нужно вернуть ошибку.

На данный момент есть 2 способа, которыми я знаю, как этого добиться:

1. Поле даты и времени базы данных

=========================
UserId | Datetime | Count
=========================
-- On every calls made (there's unique index on userId + datetime)
INSERT INTO hitrate (userId, datetime, count) VALUES (123, NOW(), 1) 
ON DUPLICATE KEY UPDATE count = count + 1;

-- Before every call, check
SELECT count FROM hitrate where userId = 123 and datetime = NOW();

Все, что мне нужно сделать, это вернуть ошибку, как только я увижу, что счетчик больше 20. Недостатком является то, что он включает в себя слишком много транзакций базы данных, и задержка между ними убивает, так что этот метод большой нет.

2. HashMap

private static HashMap<String, Integer> hitrate = new HashMap<String, Integer>();

String tag = inUsername + "-" + (System.currentTimeMillis() / 1000);

Integer count = hitrate.get(tag);
if (count == null) {
    hitrate.put(tag, 1);
} else {
    if (count >= 20) {
        // return error;
    } else {
        count++;
        hitrate.put(tag, count);
    }
}

Это более эффективно, когда речь идет о необходимых ресурсах и времени. Но дело в том, что мой hashmap будет становиться все больше и больше.

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

Спасибо.

1 Ответ

0 голосов
/ 02 июля 2018

Похоже, вы ищете что-то под названием «Ограничитель скорости». Это можно сделать разными способами. Например, в хорошо известной Гуаве библиотеке

есть ограничение скорости

Реализация его через СУБД не является хорошим подходом IMO, потому что вызовы базы данных довольно дороги, хотя это может быть жизнеспособным решением для небольших установок.

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

Если у вас есть такая настройка, вам придется перейти к «распределенному» решению.

Одно такое решение закончилось Redis .

Для этого есть даже библиотека: ratelimitj .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...