ASP.NET Core中使用滑动窗口限流的问题举例分析

技术ASP.NET Core中使用滑动窗口限流的问题举例分析本篇内容主要讲解“ASP.NET Core中使用滑动窗口限流的问题举例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家

本文内容主要讲解“ASP中使用滑动窗口限制电流问题的实例分析。网芯”。感兴趣的朋友不妨看看。本文介绍的方法简单、快速、实用。让边肖带你学习“ASP中使用滑动窗口限流问题的实例分析。网芯”!

滑动窗口算法用于处理时间段内请求的不均匀分布,能够更准确地处理流量变化。众所周知的应用场景是TCP协议的流量控制,但今天我们要讲的是服务限流场景中的应用。

算法原理

假设业务需要每秒限制电流100次。我们先来看看固定窗口算法的两个问题:

00-1010如下图所示,仅第1秒和第2秒的请求数不超过100,因此固定窗口算法不会触发电流限制。但前一秒最后500 ms的请求数加上第二秒前500ms的请求数超过100,此时可能会给系统带来危害,使用固定窗口算法时无法检测到这种情况。

ASP.NETCore中使用滑动窗口限流的问题举例分析

漏检

对于漏检的问题,可以说可以将时间窗口设置为500ms,将限流阈值设置为50。然后看下图,除了第二个计数周期超过50触发限流外,前一个和后一个计数周期的请求都是正常的,甚至没有超过阈值的50%。可能第二个计数周期的情况太特殊,一天之内不会出现第二次。如果不影响系统,你能适应吗?不要。固定窗口算法此时会过于死板。

ASP.NETCore中使用滑动窗口限流的问题举例分析

那么滑动窗口如何解决这两个问题呢?我们先来看看图片:

ASP.NETCore中使用滑动窗口限流的问题举例分析

如上图所示:

滑动窗口的时间跨度为1秒,每个小计数周期的时间跨度为500 ms,这里滑动窗口包含2个小计数周期。

随着时间的推移,滑动窗口中包含的小计数周期将在500ms内向前移动,但它始终包含两个小计数周期。

在判断是否限制电流时,需要将当前滑动窗口中包含的两个小计数周期的计数值相加。

与固定窗口计数算法相比,滑动窗口可以有效减少漏检。如上图所示,当滑动窗口移动到500-1500毫秒时,如果总数超过100,就会触发限流。滑动窗口不会在0-1000毫秒和1000-2000毫秒触发电流限制。即使小周期的计数值超过阈值的一半,但总数不超过100,也不会限制电流,可以应对罕见的突发流量情况。

从分析中可以看出,滑动窗口划分的小周期越多,检测越准确,但是用于跟踪的计数越多,使用的内存和计算就越多。

00-1010这里有两种实现方法:进程内内存滑动窗口算法和基于Redis的滑动窗口算法。

00-1010这里介绍一种高性能的方法,利用数组实现滑动窗口,这是循环队列的特例,如下图所示:

ASP.NETCore中使用滑动窗口限流的问题举例分析

假设滑动窗口需要5个小的计数周期,初始化一个长度为5的整数数组,数字代表数组中的哪个元素。

我们知道队列有头有尾。我们从队列的头部获取数据,并将数据插入队列的尾部。括号中的数字表示队列中的元素。

当滑动窗口向前移动时,队列的尾部向右移动一位,队列的头部也向右移动一位。

将队列的尾部和队列的头部向右移动可能会溢出数组,所以让它们返回到数组的起始位置,即图中数组的第一个位置。

关于这个算法的详细介绍,可以看这篇文章:如何用数组实现滑动窗口。

00-1010基于Redis也可以使用类似循环队列的方法,比如定义5 KVs作为数组的5个元素。但是,我之前用了更直观的方式来实现。每个小计数周期都会创建一个KV,同时设置一个绝对超过滑动窗口时间跨度的到期时间,这样未使用的小计数周期就不会一直占用内存。在判断是否触发限流时,累加这些小滑窗的计数值就足够了。当然,在实际实现中,我们需要改进一些细节,比如如何找到这些小的计数周期。会有很多方案,可以保存,也可以临时计算。

这些操作逻辑可以封装在Lua脚本中。因为Lua脚本在热地Redis执行时也是原子操作

s的限流计数在分布式部署时天然就是准确的。

应用算法

这里以限流组件 FireflySoft.RateLimit 为例,实现ASP.NET Core中的滑动窗口限流。

1、安装Nuget包

有多种安装方式,选择自己喜欢的就行了。

包管理器命令:

Install-Package FireflySoft.RateLimit.AspNetCore

或者.NET命令:

dotnet add package FireflySoft.RateLimit.AspNetCore

或者项目文件直接添加:

<ItemGroup>
<PackageReference Include="FireflySoft.RateLimit.AspNetCore" Version="2.*" />
</ItemGroup>

2、使用中间件

在Startup中使用中间件,演示代码如下(下边会有详细说明):

public void ConfigureServices(IServiceCollection services)
        {
           ...
           app.AddRateLimit(new InProcessSlidingWindowAlgorithm(
                new[] {
                		// 构造函数有两个参数:滑动窗口的时间长度、小计数周期的时间长度
                    new SlidingWindowRule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1))
                    {
                        ExtractTarget = context =>
                        {
                        		// 提取限流目标
                            return (context as HttpContext).Request.Path.Value;
                        },
                        CheckRuleMatching = context =>
                        {
                        		// 判断当前请求是否需要限流处理
                            return true;
                        },
                        Name="sliding window limit rule",
                        LimitNumber=100, // 限流阈值,这里即5秒最多100次请求
                    }
                })
            );
            ...
        }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            ...
            app.UseRateLimit();
            ...
        }

如上需要先注册服务,然后使用中间件。

注册服务的时候需要提供限流算法和对应的规则:

  • 这里使用进程内固定窗口算法InProcessSlidingWindowAlgorithm,还可以使用RedisSlidingWindowAlgorithm,需要传入一个Redis连接。两种算法都支持同步和异步方法。

  • 限流阈值是100,限流滑动窗口是5秒,小计数周期是1秒。

  • ExtractTarget用于提取限流目标,这里是每个不同的请求Path。如果有IO请求,这里还支持对应的异步方法ExtractTargetAsync。

  • CheckRuleMatching用于验证当前请求是否限流。如果有IO请求,这里还支持对应的异步方法CheckRuleMatchingAsync。

  • 默认被限流时会返回HttpStatusCode 429,可以在AddRateLimit时使用可选参数error自定义这个值,以及Http Header和Body中的内容。

基本的使用就是上边例子中的这些了。

如果还是基于传统的.NET Framework,则需要在Application_Start中注册一个消息处理器RateLimitHandler,算法和规则部分都是共用的,具体可以看Github上的使用说明:https://github.com/bosima/FireflySoft.RateLimit

FireflySoft.RateLimit 是一个基于 .NET Standard 的限流类库,其内核简单轻巧,能够灵活应对各种需求的限流场景。

其主要特点包括:

  • 多种限流算法:内置固定窗口、滑动窗口、漏桶、令牌桶四种算法,还可自定义扩展。

  • 多种计数存储:目前支持内存、Redis两种存储方式。

  • 分布式友好:通过Redis存储支持分布式程序统一计数。

  • 限流目标灵活:可以从请求中提取各种数据用于设置限流目标。

  • 支持限流惩罚:可以在客户端触发限流后锁定一段时间不允许其访问。

  • 动态更改规则:支持程序运行时动态更改限流规则。

  • 自定义错误:可以自定义触发限流后的错误码和错误消息。

  • 普适性:原则上可以满足任何需要限流的场景。

到此,相信大家对“ASP.NET Core中使用滑动窗口限流的问题举例分析”有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/141692.html

(0)

相关推荐