Java 构建自定义筛选器以每个标识符M个时间单位处理N个请求

Java 构建自定义筛选器以每个标识符M个时间单位处理N个请求,java,multithreading,algorithm,filter,Java,Multithreading,Algorithm,Filter,我正在尝试构建一个自定义过滤器,该过滤器将只处理每个标识符每M时间单位(比如1秒)的N个请求(比如100个)。所有大于N的请求都将被拒绝或忽略。请求是一个包含标识符、时间戳和其他卫星数据的对象(筛选器不应处理卫星数据) 第一个想法是拥有一个ConcurrentHashMap[String,AtomicInteger]这将有#个标识符的请求数,但我无法理解使用哪种数据结构来跟踪每秒的计数,该数据结构也应该能够清理,因为它将很快增长,我们不需要维护有关过去的数据 这也意味着一个可能的解决方案将具有一

我正在尝试构建一个自定义过滤器,该过滤器将只处理每个标识符每M时间单位(比如1秒)的N个请求(比如100个)。所有大于N的请求都将被拒绝或忽略。请求是一个包含标识符、时间戳和其他卫星数据的对象(筛选器不应处理卫星数据)

第一个想法是拥有一个ConcurrentHashMap[String,AtomicInteger]这将有#个标识符的请求数,但我无法理解使用哪种数据结构来跟踪每秒的计数,该数据结构也应该能够清理,因为它将很快增长,我们不需要维护有关过去的数据

这也意味着一个可能的解决方案将具有一个数据结构,该结构能够仅存储时间戳之间的增量,并确保每个标识符不超过N个请求(以M个时间单位表示)


这听起来可能是一个速率限制,可能有标准库或选项可用,但我想了解如何构建它,因此寻找一些指针而不是直接的代码解决方案

这里是一种方法

存储格式为
(时间四舍五入,计数)
的值。只有当
time\u rounded\u off=current\u time\u rounded\u off
count
时,才处理请求

当舍入时间增加时,计数器重置为0,然后再次开始处理

这种设计有助于将业务规则保持在适当的位置,但如果处理突然爆发的请求对您的基础架构来说太难,则这种设计就不太好了。为此,我建议您记录每秒处理的请求数。无论何时,只要价格降得足够低,你就可以接受另一个请求

使用这种方法,您的值将是成对的
(时间戳,平均值)
。现在更新它的过程是将时间戳更新为当前时间戳,并将平均值乘以衰减因子(取决于时间戳的差异)。如果你收到的请求比它能处理的要快,那么结果就是以正确的近似速率对它们进行采样


现在有两个参数可以使用,衰减率和平均值。您可以选择特定的速率,即每小时360000次、每分钟6000次、每秒100次和每0.1秒10次。它们之间的区别在于你必须一次性处理的“爆发”的潜在大小。

你可能想看看番石榴的课程

这是一个库类,但javadoc很好地解释了它的内部工作原理

非常简短的版本是:它的工作原理有点像一个信号灯。线程(需要处理请求)必须先从RateLimitor获得许可,然后才能被允许这样做。
速率限制器
允许以预定义速率输出

您可以在此处查看源代码: