Я пытаюсь создать 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 будет становиться все больше и больше.
Кто-нибудь имеет опыт управления этим и знает, как лучше всего использовать эту логику?
Спасибо.