zoukankan      html  css  js  c++  java
  • Rate Limiting Algorithms (限流算法)

    1. Leaky Bucket (漏桶)

            

          漏桶是一种常用的限流策略。NGINX 和 QEMU 中利用漏桶来实现限流。在漏桶模型中,桶的容量是固定的,当桶被流进的水填满时,多余的水就会溢出;虽然水可以以不同的速率流进桶中,但却必须以固定的速率从桶底部漏出。

          可以将漏桶看成一个队列,队列有固定大小的容量,元素可以以任意速率入队,但是只能以固定速率出队。如果队列满了,要入队的元素将被丢弃。

    算法伪代码:

    leaky_bucket()
        now ← current_time()
        x ← counter - (now - last_confirm_time) * leak_rate
        if x >= bucket_size
            return false             // reject the request
        counter ← max(0, x) + 1 
        last_confirm_time ← now
        return true                  // accept the request 

          漏桶可以保证请求进入其后端系统的速率,同时桶的容量限制了请求到达速率的峰值。

    2. Token Bucket (令牌桶)

             

          在令牌桶模型中,令牌以固定的速率进入桶中,如果桶已经被填满,那么后续填入的令牌会被丢弃。每个请求在进入后端系统时需要从桶中拿出一个令牌,如果桶中没有足够的令牌,那么请求就需要在队列中继续等待。

    token_bucket(n_tokens)                  
        now ← current_time()
        x ← counter + (now - last_confirm_time) * fill_rate
        if x > bucket_size
            x ← bucket_size
        n_tokens_removed ← min(x, n_tokens) 
        counter ← x - n_tokens_removed
        last_confirm_time ← now
        return n_tokens_removed

         相对于漏桶算法,令牌桶算法更宽松,它允许在短时间内有大量的请求进入后端系统。也就是说,令牌桶允许 burst traffic

    3. Fixed Window Counter

          假设限流是限制一分钟内的请求数目,那么可以只对当前1分钟内的请求数目进行统计。我们只统计 [00:00:00, 00:00:59], [00:01:00, 00:01:59], ... [23:59:00, 23:59:59] 这样的时间段内的请求数目,在任意时刻,我们只需要一个计数器。

          这种做法虽然简单,但是在一个1分钟长度的时间段内可能出现 2 * rate_limit 个请求。

          例如,请求速率限制为 100 requests / min, 那么在 1 分钟的时间窗口内的请求数目就可以达到 200。很多时候,这并不是我们期望的。

    4. Sliding Window Log

          假设我们的限流算法的时间窗口大小为1分钟,我们可以维护一个unix时间截列表,记录了过去的 1 分钟时间段内的所有请求的到达时间, 这个列表的长度就是过去1分钟内接受的请求的数目。这一算法可能需要消耗很大的存储空间,假设我们允许的最大请求数目为 500 requests / min, 那么一个列表的长度就能达到 500。想一想,如果我们维护大量这种列表的话 ...  

    5. Sliding Window Counter

          假设限流算法的时间窗口为1分钟,我们维护一个列表,列表的每一项包含两个数,一个是 unix 时间截,一个是 unix 时间截所表示的 1s 时间内的请求数目,那么 1 分钟时间窗口内的请求数目,就是这些列表项中的请求数目的和。列表的最大长度为 60。

          这个算法的基本思路就是将时间窗口划分成更小的时间片,分别对这些时间片上的请求数目做统计,这就解决了上一种算法列表长度依赖于限流速率的问题,同时能够一定程度上缓解固定窗口计数的缺陷。  

    6. 一种近似算法

          有一种非常简单的近似算法,我们维护两个计数,一个是上一分钟接受的请求数目,一个是本分钟内接受的请求数目,通过简单的计算我们可以估计在过去1分钟时间窗口内的请求数目。具体算法通过举例来说明。

          假设我们允许在一分钟内的最大请求数目是 50,  即任意的 1 分钟长度的时间段内的请求数目不能超过50。

          假设当前时间为 21:32:15, 那么上一分钟是 [21:31:00, 21:31:59],在这段时间内有 42 个请求。本分钟为 [21:32:00, 21:32:59], 本分钟过去了 15s,在这 15s 时间里我们已经接受了18个请求,由此,我们对在过去的 1 分钟 [21:31:16, 21:32:15] 时间窗口内请求速率可以做出如下估计:

                    estimated_rate = 42 * (60 - 15) / 60 + 18 = 49.5  

          如果有新的请求在 [21:31:15, 21:31:16) 到达,  若接收请求,估计值就会超过 50,  违反了请求速率限制。

                

    参考

         1.  Nikrad Mahdi (April 12, 2017). "An Alternative Approach to Rate Limiting"

         2.  How we built rate limiting capable of scaling to millions of domains

  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/william-cheung/p/8763482.html
Copyright © 2011-2022 走看看