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

时间:2018-08-15 16:12:37

标签: java multithreading algorithm filter

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

首先想到的是要拥有一个ConcurrentHashMap [String,AtomicInteger],该标识符应具有每个标识符的请求数,但是我无法理解每秒使用哪个数据结构来跟踪这些计数,并且该数据结构也应该是能够清理,因为它很快就会增长,我们不需要维护过去的数据。

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

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

>

2 个答案:

答案 0 :(得分:0)

这是一种方法。

存储格式为(time_rounded_off, count)的值。仅当time_rounded_off = current_time_rounded_offcount < max_count时,您才处理请求。

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

此设计对于保持业务规则有效,但是如果在基础架构上处理突发的请求太难了,则不是很好。为此,我建议您保持exponential moving average的每秒处理请求数。只要下降到足够低的水平,您就可以提出另一个请求。

使用这种方法,您的值将是(timestamp, average)形式的对。现在,更新它的过程是将时间戳更新为当前时间戳,然后将平均值乘以衰减因子(这取决于时间戳的差异)。如果收到请求的速度超出其处理速度,那么结果就是以正确的近似速率对其进行采样。

您现在可以使用两个参数,衰减率和平均值。您可以为特定速率选择是否表示每小时360,000,每小时6000,每秒100和每0.1秒10。它们之间的区别是您必须一次处理“爆发”的潜在大小。

答案 1 :(得分:0)

您可能想看看番石榴的RateLimiter类。

这是一个库类,但是javadoc很好地解释了其内部工作方式。

非常简短的版本是:它的工作原理有点像Semaphore。线程(需要处理请求)必须先从RateLimiter获得许可,然后才允许这样做。 RateLimiter的输出允许以预定的速率。

您可以在此处查看源代码:https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/RateLimiter.java