Java Servlet跟踪API命中率

时间:2018-06-29 08:58:47

标签: java servlets

我正在尝试使用非常基本的j2ee servlet和MySQL构建HTTP API。

有一个要求,我必须限制特定用户调用我们服务器的频率。假设当我检测到他们的TPS限制为20时,一旦他们在同一秒进行21次通话,我就需要返回错误。

到目前为止,我知道有两种方法可以实现:

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);
    }
}

在所需的资源和时间方面,这种方法效率更高。但是问题是我的哈希图会越来越大。

有人有管理此方面的经验,并且知道采用这种逻辑的最佳方法是什么吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

您似乎正在寻找一种叫做“速率限制器”的东西。 这可以通过多种方式来完成。 例如,著名的Guava库中有一个限速器

在RDBMS上实现它不是IMO的好方法,因为数据库调用非常昂贵,尽管它对于小型设置来说是可行的解决方案。

但是,与您提供的哈希图解决方案和Guava方法相比,如果您的设置中有更多服务器集群并且想要限制用户访问权限,而无论用户调用哪个服务器,它都将起作用。 / p>

如果您具有这种设置,则必须使用“分布式”解决方案。

一种这样的解决方案已经超过Redis

甚至还有一个库:ratelimitj

相关问题