为 Web 请求实现速率限制算法的最佳方法是啥?

Posted

技术标签:

【中文标题】为 Web 请求实现速率限制算法的最佳方法是啥?【英文标题】:What is the best way to implement a rate-limiting algorithm for web requests?为 Web 请求实现速率限制算法的最佳方法是什么? 【发布时间】:2010-11-29 19:55:15 【问题描述】:

可能/部分重复:

What’s a good rate limiting algorithm? Throttling method calls to M requests in N seconds Best way to implement request throttling in ASP.NET MVC?

我正在寻找为 Web 应用程序实施移动时间窗口速率限制算法以减少垃圾邮件或暴力攻击的最佳方法。

使用示例为“过去 5 分钟内来自给定 IP 的最大失败登录尝试次数”、“过去 N 分钟内(帖子/投票/等...)的最大数量”。

我更喜欢使用移动时间窗口算法,而不是每 X 分钟硬重置一次统计信息(如 twitter api)。

这适用于 C#/ASP.Net 应用程序。

【问题讨论】:

我认为所提供的任何骗子都没有真正用 asp.net/c# 来回答这个问题。 @spender:因此“可能”这个词;-) 真的是针对“接近”的选民而不是原始问题内容。 @Lamar 你能告诉我们你最终使用了什么方法,你喜欢它吗? 【参考方案1】:

我一直在研究一种新的基于 redis 的限速方法:http://blog.jnbrymn.com/2021/03/18/estimated-average-recent-request-rate-limiter.html

它比我见过的许多其他方法更简单,因为它不需要您不断创建新的 redis 键(例如,不是每个用户每分钟窗口一个,而是每个用户一个)。它有一些关于“健忘和宽恕”的好属性,例如,滥用用户不能在下一分钟窗口内再次犯罪。它也有一个很好的解释,因为速率限制器的状态对应于用户最近请求率的估计。

【讨论】:

喜欢阅读您的博文。干得好。 谢谢!我们正在考虑在 GitHub 上实现它。 酷。如果/当你这样做时,请链接回购。【参考方案2】:

我刚刚添加了问题的答案Block API requests for 5 mins if API rate limit exceeds. 我使用HttpRuntime.Cache 每分钟只允许 60 个请求。超过限制将在接下来的 5 分钟内阻止 API。

【讨论】:

【参考方案3】:

只是为这个问题添加一个更“现代”的答案:对于 .NET WebAPI,WebApiThrottle 非常出色,并且可以满足您开箱即用的所有需求。

也是available on NuGet。

实施仅需一分钟左右,而且高度可定制:

config.MessageHandlers.Add(new ThrottlingHandler()

    Policy = new ThrottlePolicy(perSecond: 1, perMinute: 30, perHour: 500, perDay:2000)
    
        IpThrottling = true,
        ClientThrottling = true,
        EndpointThrottling = true
    ,
    Repository = new CacheRepository()
);

【讨论】:

这个项目还活着吗?【参考方案4】:

你会发现这个页面很有趣:

http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx

要注意的部分开始如下:

防止拒绝服务 (DOS) 攻击

Web 服务对黑客来说是最有吸引力的目标,因为即使是学龄前的黑客也可以通过重复调用 Web 服务来破坏服务器,而这会带来昂贵的工作。

编辑:这里有类似的问题:

Best way to implement request throttling in ASP.NET MVC?

【讨论】:

【参考方案5】:

使用基于内存的快速哈希表,例如 memcached。密钥将是您要限制的目标(例如 IP),每个存储值的到期时间应该是最大限制时间。

为每个键存储的值将包含他们在执行该操作时最近 N 次尝试的序列化列表,以及每次尝试的时间。

【讨论】:

所以对于每次尝试,我都会反序列化缓存列表,在时间窗口之外切掉条目,添加新条目,计数项目,并更新缓存? @Lamar 您可以使用 Redis 代替 Memcached。 Redis 内置了对列表和 get-first 和 get-last 的支持——我认为使用 Redis 你不需要反序列化整个列表。谷歌“redis 速率限制” @KajMagnus Redis 绝对是解决这个问题的正确方法。支持列表并将其应用于速率限制可以很好地协同工作。【参考方案6】:

我们发现Token Bucket 是这种速率限制的更好算法。它广泛用于路由器/交换机,因此我们的操作人员更熟悉这个概念。

【讨论】:

听起来您是在建议在网络交换机层实现。这可能是一个非常好的安全实施,但在无服务器环境日益普及的情况下,当底层硬件基础设施由云提供商托管时,网络层保护更难实施。

以上是关于为 Web 请求实现速率限制算法的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

高并发服务限流实践

Angular - http 拦截器 - http 速率限制器 - 滑动窗口

中小型项目请求限流设计

基于Redis实现分布式应用限流--转

限流算法 - 基本实现

如何用 Java 来构建一个简单的速率限制器?