• 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

  • 相关阅读:
    呃,如何使 .NET 程序,在 64位 系统 中,以 32位 模式运行。
    [转载]Cortana 设计指导方针
    Could not load file or assembly System.Core, Version=2.0.5.0
    wpf中用户控件的属性重用
    浅谈AutoResetEvent的用法
    WPF异步载入图片,附带载入中动画
    WPFLoading遮层罩
    获取WPF的DataGrid控件中,是否存在没有通过错误验证的Cell
    WPF通过异常来验证用户输入
    WPF验证之——必填验证
  • 原文地址:https://www.cnblogs.com/william-cheung/p/8763482.html
Copyright © 2020-2023  润新知