网页请求的流量控制算法有哪些最佳实现方式?

31

可能/部分重复:

我正在寻找一种最佳方式来实现一个动态时间窗口限速算法,用于减少网络应用程序中的垃圾邮件或暴力攻击。

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

我更喜欢使用一个动态时间窗口算法,而不是每隔X分钟进行硬重置统计的方法(例如Twitter API)。

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


我认为提供的任何重复答案都没有以asp.net/c#的角度回答这个问题。 - spender
@spender:因此,那个词“可能”;-) - Argalatyr
这实际上是针对“关闭”投票者而不是原始问题内容的。 - spender
1
@Lamar,你能告诉我们你最终使用了什么方法,以及你喜欢它吗? - Mark E. Haase
6个回答

28

我们发现对于这种速率限制,令牌桶算法是更好的算法。它在路由器/交换机中被广泛使用,因此我们的运维人员更熟悉这个概念。


2
听起来你在建议在网络交换机层面上实现。这可以是一个非常好的安全实现,但随着无服务器环境的日益普及,当基础硬件基础设施由云提供商托管时,网络层保护更难实现。 - benhorgen

13

为了对这个问题增加一个更“现代”的答案:对于 .NET WebAPI,WebApiThrottle 是绝佳的,它可能已经自带了你所需要的所有功能。

它也可以在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()
});

这个项目还在继续吗? - JobaDiniz

12

使用像memcached这样快速的基于内存的哈希表。键将是您所限制的目标(例如,IP地址),每个存储值的过期时间应为最大限制时间。

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


2
那么对于每次尝试,我会反序列化缓存列表,剪切超出时间窗口的条目,添加新条目,计算项目数量并更新缓存? - Lamar
1
@Lamar 你可以使用Redis代替Memcached。Redis内置支持列表和获取第一个和最后一个元素 - 我认为使用Redis时,你不需要对整个列表进行反序列化。在Google上搜索“redis限速”即可。 - KajMagnus
@KajMagnus Redis 绝对是这个问题的正确解决方案。支持列表并将其应用于速率限制非常契合。 - Lamar

2

2

2
我一直在研究一种基于redis的新速率限制方法:http://blog.jnbrymn.com/2021/03/18/estimated-average-recent-request-rate-limiter.html 与许多其他方法相比,它更简单,因为它不需要您不断创建新的redis键(例如,每分钟窗口每个用户一个键,而只需每个用户一个键)。它具有关于“遗忘和宽恕”的一些好特性,以便例如滥用用户无法在下一个分钟窗口中再次犯错。它还有一个很好的解释,即速率限制器的状态对应于对用户最近请求速率的估计。

1
喜欢阅读你的博客文章,做得很好! - David Peden
谢谢!我们正在考虑在GitHub上实施它。 - JnBrymn
很好。如果您完成了,请链接代码库。 - David Peden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接