ASP.NET Core基于滑动窗口实现限流控制

目录
  • 前言:
  • 二、固定窗口算法
  • 三、滑动窗口算法
  • 四、实现
  • 六、使用
  • 结论:

前言:

在实际项目中,为了保障服务器的稳定运行,需要对接口的可访问频次进行限流控制,避免因客户端频繁请求导致服务器压力过大。

而​AspNetCoreRateLimit是目前ASP.NET Core下最常用的限流解决方案。

查看它的实现代码,我发现它使用的固定窗口算法。

var entry = await _counterStore.GetAsync(counterId, cancellationToken);

if (entry.HasValue)
{
    // entry has not expired
    if (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow)
    {
        // increment request count
        var totalCount = entry.Value.Count + _config.RateIncrementer?.Invoke() ?? 1;

        // deep copy
        counter = new RateLimitCounter
        {
            Timestamp = entry.Value.Timestamp,
            Count = totalCount
        };
    }
}

二、固定窗口算法

固定窗口算法是将时间线划分为固定大小的窗口,并为每个窗口分配一个计数器。每个请求,根据其到达时间,被映射到一个窗口。如果窗口中的计数器已达到限制,则拒绝落在此窗口中的请求。

例如,如果我们将窗口大小设置为one分钟,每分钟允许ten个请求:

ASP.NET Core基于滑动窗口算法实现限流控制 #yyds干货盘点#_滑动窗口

59秒的请求将被阻止,因为这时已经接受了10个请求。1分钟时计数器归零,所以1分01秒的请求可以接受。

​​固定窗口算法的问题主要在于,如果在窗口边缘发生大量请求,会导致限流策略失效。​​

比如,在59秒接收了9个请求,在1分01秒又可以再接收10个请求,相当于每分钟允许了20个请求。

三、滑动窗口算法

滑动窗口类似于固定窗口算法,但它通过将前一个窗口中的加权计数添加到当前窗口中的计数来计算估计数,如果估计数超过计数限制,则请求将被阻止。

具体公式如下:

估计数 = 前一窗口计数 * (1 - 当前窗口经过时间 / 单位时间) + 当前窗口计数

例如,假设限制为每分钟10个:

窗口[00:00, 00:01)中有9个请求,窗口[00:01, 00:02)中有5个请求。对于01:15到达的请求,即窗口[00:01, 00:02)的25%位置,通过公式计算请求计数:9 x (1 - 25%) + 5 = 11.75 > 10. 因此我们拒绝此请求。

​​即使两个窗口都没有超过限制,请求也会被拒绝,因为前一个和当前窗口的加权和确实超过了限制。​​

四、实现

根据上面的公式,实现滑动窗口算法代码如下:

public class SlidingWindow
{
    private readonly object _syncObject = new object();

    private readonly int _requestIntervalSeconds;
    private readonly int _requestLimit;

    private DateTime _windowStartTime;
    private int _prevRequestCount;
    private int _requestCount;

    public SlidingWindow(int requestLimit, int requestIntervalSeconds)
    {
        _windowStartTime = DateTime.Now;
        _requestLimit = requestLimit;
        _requestIntervalSeconds = requestIntervalSeconds;
    }

    public bool PassRequest()
    {
        lock (_syncObject)
        {
            var currentTime = DateTime.Now;
            var elapsedSeconds = (currentTime - _windowStartTime).TotalSeconds;

            if (elapsedSeconds >= _requestIntervalSeconds * 2)
            {
                _windowStartTime = currentTime;
                _prevRequestCount = 0;
                _requestCount = 0;

                elapsedSeconds = 0;
            }
            else if (elapsedSeconds >= _requestIntervalSeconds)
            {
                _windowStartTime = _windowStartTime.AddSeconds(_requestIntervalSeconds);
                _prevRequestCount = _requestCount;
                _requestCount = 0;

                elapsedSeconds = (currentTime - _windowStartTime).TotalSeconds;
            } 

            var requestCount = _prevRequestCount * (1 - elapsedSeconds / _requestIntervalSeconds) + _requestCount + 1;
            if (requestCount <= _requestLimit)
            {
                _requestCount++;
                return true;
            }
        }

        return false;
    }
}

如果最近的2次请求相距2个窗口时间,则可以认为前一窗口计数为0,重新开始计数。

六、使用

新建Middleware,使用滑动窗口算法进行限流:

public class RateLimitMiddleware : IMiddleware
{
    private readonly SlidingWindow _window;

    public RateLimitMiddleware()
    {
        _window = new SlidingWindow(10, 60);
    }
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        if (!_window.PassRequest())
        {
            context.SetEndpoint(new Endpoint((context) =>
            {
                context.Response.StatusCode = StatusCodes.Status403Forbidden;
                return Task.CompletedTask;
            },
                        EndpointMetadataCollection.Empty,
                        "限流"));
        }

        await next(context);
    }
}

​​需要注意的是,我们注册Middleware时,必须使用单例模式,保证所有请求通过同一SlidingWindow计数:​​

services.AddSingleton<RateLimitMiddleware>();

结论:

使用滑动窗口算法,可以有效避免固定窗口算法存在的窗口边缘大量请求无法限制的问题。

到此这篇关于ASP.NET Core基于滑动窗口实现限流控制的文章就介绍到这了,更多相关ASP.NET Core基于滑动窗口实现限流控制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • ASP.NET Core中间件实现限流的代码

    目录 一.限流算法 1.计数器算法 1.1固定窗口算法 1.2滑动窗口算法 2.令牌桶算法 3.漏桶算法 二.ASP.NETCore中间件实现限流 1.中间件代码 2.在管道中的使用 一.限流算法 在高并发系统中,有三把利器用来保护系统:缓存.降级和限流. 本文主要是介绍限流,限流算法主要有以下三种: 1.计数器算法 固定窗口 滑动窗口 2.令牌桶算法 3.漏桶算法 1.计数器算法 1.1 固定窗口算法 计数器算法是限流算法里最简单也是最容易实现的一种算法.比如我们规定,对于A接口来说,我们1分

  • ASP.NET Core中使用滑动窗口限流的问题及场景分析

    目录 算法原理 漏检 太刚 算法实现 进程内即内存滑动窗口算法 基于Redis的滑动窗口算法 应用算法 1.安装Nuget包 2.使用中间件 滑动窗口算法用于应对请求在时间周期中分布不均匀的情况,能够更精确的应对流量变化,比较著名的应用场景就是TCP协议的流量控制,不过今天要说的是服务限流场景中的应用. 算法原理 这里假设业务需要每秒钟限流100次,先来看固定窗口算法的两个问题: 漏检 如下图所示,单看第1秒和第2秒,其请求次数都没有超过100,所以使用固定窗口算法时不会触发限流.但是第1秒的后

  • ASP.NET Core中的策略授权和ABP授权

    目录 ASP.NETCore中的策略授权 策略 定义一个Controller 设定权限 定义策略 存储用户信息 标记访问权限 认证:Token凭据 颁发登录凭据 自定义授权 IAuthorizationService ABP授权 创建ABP应用 定义权限 ASP.NET Core 中的策略授权 首先我们来创建一个 WebAPI 应用. 然后引入 Microsoft.AspNetCore.Authentication.JwtBearer 包. 策略 Startup 类的 ConfigureServ

  • ASP.NET Core读取配置文件

    ASP.NET Core 中,可以使用 ConfigurationBuilder 对象来构建. 主要分为三部:配置数据源 -> ConfigurationBuilder -> 使用. 数据源可来自字典或配置文件. 数据源要么继承 IConfigurationSource ,要么从配置文件中读取. 1,来自字典 我们先使用字典存储键值对,来设置配置, test = 配置,然后使用 ConfigurationBuilder.Add() 方法添加数据源, Add 方法可以添加继承了 IConfigu

  • Redis数据库基础与ASP.NET Core缓存实现

    目录 基础 Redis库 连接Redis 能用redis干啥 Redis数据库存储 字符串 订阅发布 RedisValue ASP.NETCore缓存与分布式缓存 内存中的缓存 ASP.NETCore的内存缓存 在内存中缓存.存储数据 IMemoryCache MemoryCache 分布式缓存 IDistributedCache Redis缓存 基础 Redis 库 C# 下 Redis-Client 开源的库很多,有 BeetleX.Redis.csredis.Nhiredis.redis-

  • ASP.NET Core中Cookie验证身份用法详解

    目录 添加配置 ASP.NETCore1.x ASP.NETCore2.x 创建身份认证Cookie ASP.NETCore1.x ASP.NETCore2.x Signingout(登出) ASP.NETCore1.x ASP.NETCore2.x 服务端变化反馈 ASP.NETCore1.x ASP.NETCore2.x Cookie设置选项 ASP.NETCore1.x ASP.NETCore2.x 持久Cookie ASP.NETCore1.x ASP.NETCore2.x 绝对到期时间

  • Asp.NET Core 限流控制(AspNetCoreRateLimit)的实现

    起因: 近期项目中,提供了一些调用频率较高的api接口,需要保障服务器的稳定运行:需要对提供的接口进行限流控制.避免因客户端频繁的请求导致服务器的压力. 一.AspNetCoreRateLimit 介绍 AspNetCoreRateLimit 是一个ASP.NET Core速率限制的解决方案,旨在控制客户端根据IP地址或客户端ID向Web API或MVC应用发出的请求的速率.AspNetCoreRateLimit包含一个 IpRateLimitMiddleware 和 ClientRateLim

  • ASP.NET Core基于滑动窗口实现限流控制

    目录 前言: 二.固定窗口算法 三.滑动窗口算法 四.实现 六.使用 结论: 前言: 在实际项目中,为了保障服务器的稳定运行,需要对接口的可访问频次进行限流控制,避免因客户端频繁请求导致服务器压力过大. 而​AspNetCoreRateLimit是目前ASP.NET Core下最常用的限流解决方案. 查看它的实现代码,我发现它使用的固定窗口算法. var entry = await _counterStore.GetAsync(counterId, cancellationToken); if

  • ASP.NET Core使用固定窗口限流

    目录 算法原理 算法实现 进程内即内存固定窗口算法 基于Redis的固定窗口算法 算法应用 1.安装Nuget包 2.使用中间件 算法原理 固定窗口算法又称计数器算法,是一种简单的限流算法.在单位时间内设定一个阈值和一个计数值,每收到一个请求则计数值加一,如果计数值超过阈值则触发限流,如果达不到则请求正常处理,进入下一个单位时间后,计数值清零,重新累计. 如上图所示,时间单位是1秒,阈值是3. 第1秒3个请求,不会触发限流: 第2秒1个请求,不会触发限流: 第3秒4个请求,这一秒的前3个请求正常

  • ASP.NET Core中使用令牌桶限流的实现

    在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某一秒钟会达到120次请求,接着很快又会恢复正常,假设这种突发的流量不会对系统稳定性带来实质性的影响,则可以在一定程度上允许这种瞬时的突发流量,从而为用户带来更好的可用性体验.这就是令牌桶算法的用武之地. 该算法的基本原理是:有一个令牌桶,容量是X,每Y单位时间会向桶中放入Z个令牌,如果桶中的令牌数超

  • Asp.Net Core基于JWT认证的数据接口网关实例代码

    前言 近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求用Aps.Net Core做数据网关服务且基于JWT认证实现对前后端分离的数据服务支持,于是想到我一直做.Net开发,问我是否对.Net Core有所了解?能不能做个简单Demo出来看看?我说,分道扬镳之后我不是调用别人的接口就是提供接口给别人调用,于是便有了以下示例代码. 示例要求能演示获取Token及如何使用该Token访问数据资源,在Demo中实现

  • ASP.Net Core基于EF6、Unitwork、Autofac实现Repository模式

    一.实现的思路和结构图 Repository的共同性 有一些公共的方法(增删改查), 这些方法无关于Repository操作的是哪个实体类,可以把这些方法定义成接口IRepository,然后有个基类BaseRepository实现该接口的方法.常见的方法,比如Find, Filter, Delete, Create等 Repository的差异性 每个Repository类又会有一些差异性,应当允许它们能够继承BaseRepository之外,还能够再扩展自己的一些方法.所以每个类都可以再定义

  • ASP.NET Core基于现有数据库创建EF模型

    1.简介 Entity Framework Core可通过数据库提供给应用程序的插件访问许多不同的数据库.我们可以通过使用Entity Framework Core构建执行基本数据访问的ASP.NET Core MVC应用程序,对现有数据库进行反向工程以便创建Entity Framework模型. 2.创建数据库 我们可以通过Visual Studio创建一个数据库再进行演示,步骤如下:●打开Visual Studio开发工具●“工具”>“连接到数据库”●选择“Microsoft SQL Ser

  • ASP.Net Core基于ABP架构配置To Json序列化

    一. 前言 我们采用ABP架构用MVC Controller或Web API返回给前端结果ToJson序列化后得到的属性命名都是采用js的驼峰格式,即首字母小写,后面单词首字母大写的格式(如:后台属性名为OrderName,返回的前端js为orderName).但在实际项目开发中由于某种原因(比如给老系统提供接口或现有系统集成等)需要采用给后台属性名一致或自己特定的格式,下面就介绍一下基于ABP架构ToJson如何修改默认配置和自定义配置. 二. 修改ToJson序列化默认配置 在Startup

  • 解决ASP.NET Core中使用漏桶算法限流的问题

    目录 算法原理 算法实现 进程内即内存漏桶算法 基于Redis的漏桶算法 应用算法 1.安装Nuget包 2.使用中间件 漏桶算法是限流的四大主流算法之一,其应用场景各种资料中介绍的不多,一般都是说应用在网络流量控制中.这里举两个例子: 1.目前家庭上网都会限制一个固定的带宽,比如100M.200M等,一栋楼有很多的用户,那么运营商怎么保证某些用户没有使用过多的带宽,从而影响到别人呢?这时就可以使用漏桶算法,限制每个用户访问网络的最大带宽,当然实际会比这复杂很多. 2.有一个祖传接口,当时写的时

  • 深入解读ASP.NET Core身份认证过程实现

    长话短说:上文我们讲了 ASP.NET Core 基于声明的访问控制到底是什么鬼? 今天我们乘胜追击:聊一聊ASP.NET Core 中的身份验证. 身份验证是确定用户身份的过程. 授权是确定用户是否有权访问资源的过程. 1. 万变不离其宗 显而易见,一个常规的身份认证用例包括两部分: ① 对用户进行身份验证 ② 在未经身份验证的用户试图访问受限资源时作出反应 已注册的身份验证处理程序及其配置选项被称为"方案",方案可用作一种机制,供用户参考相关处理程序的身份验证.挑战和禁止行为. 我

随机推荐