代码之家  ›  专栏  ›  技术社区  ›  JRG

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

  •  0
  • JRG  · 技术社区  · 6 年前

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

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

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

    这可能听起来像一个速率限制器,可能有标准库或选项可用,但我想了解如何构建它 .

    2 回复  |  直到 6 年前
        1
  •  0
  •   btilly    6 年前

    存储以下形式的值 (time_rounded_off, count) . 只有在以下情况下才处理请求 time_rounded_off = current_time_rounded_off count < max_count .

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

    这种设计有助于将业务规则保持在适当的位置,但如果处理突然爆发的请求对您的基础结构来说太困难,则这种设计就不好了。为此,我建议你保持冷静 exponential moving average 每秒处理的请求数。无论什么时候下降到足够低,你都可以接受另一个请求。

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

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

        2
  •  0
  •   bowmore    6 年前

    你可以去看看番石榴 RateLimiter

    它是library类,但是javadoc很好地解释了它是如何在内部工作的。

    最简短的版本是:它的工作原理有点像 Semaphore RateLimiter 输出允许以预定义的速率进行。

    https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/RateLimiter.java