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

前言

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

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

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

var entry = await _counterStore.GetAsync(counterId, cancellationToken);if (entry.HasValue)
{// entry has not expiredif (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow){// increment request countvar totalCount = entry.Value.Count + _config.RateIncrementer?.Invoke() ?? 1;// deep copycounter = new RateLimitCounter{Timestamp = entry.Value.Timestamp,Count = totalCount};}
}

固定窗口算法

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

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

0d872cbe024d573c7ea9bbd0a619d8a5.png

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

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

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

滑动窗口算法

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

具体公式如下:

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

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

a1da9c5354baeed9dbbe7acfd6e9af5c.png

窗口[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>();

结论

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

想了解更多内容,请关注我的个人公众号”My IO“

参考资料

[1]

AspNetCoreRateLimit: https://github.com/stefanprodan/AspNetCoreRateLimit

e4eb6e78bbd03381b1e887116beeb176.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/290986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux操作系统cp命令

转载于:https://www.cnblogs.com/skl374199080/p/3863918.html

sql必读的九本书

2019独角兽企业重金招聘Python工程师标准>>> 原文地址 直接上书(书籍以后会陆续加上去)书籍下载地址 《MySQL必知必会》《SQL学习指南&#xff08;第2版 修订版&#xff09;》《MySQL技术内幕——InnoDB存储引擎》《Redis设计与实现》《ZooKeeper&#xff1a;分布式…

C语言之加入头文件<stdbool.h>可以使用true和false

1、头文件<stdbool.h>介绍 &#xff08;1&#xff09;使用了<stdbool.h>后&#xff0c;可使用true和false来表示真假。 &#xff08;2&#xff09;在循环语句中进行变量声明是C99中才有的&#xff0c;因此编译时显式指明 gcc -stdc99 prime.c 2、最简单的例子 3、…

Nginx负载均衡+转发策略

负载均衡负载均衡(详解)https://cloud.tencent.com/developer/article/1526664--示例1upstream www_server_pool { server 10.0.0.5; server 10.0.0.6&#xff1a;80 weight1 max_fails1 fails_timeout10s; server 10.0.0.7&#xff1a;80 weight1 max_fails2 fails_timeo…

教育行业的互联网焦虑症

2019独角兽企业重金招聘Python工程师标准>>> 文/阑夕 2007年&#xff0c;前新东方名师刘一男在新东方在线&#xff08;网校&#xff09;上的全年课程收入是三千元&#xff0c;四年之后的2011年&#xff0c;这个数字飙升到了四十万&#xff0c;已经和刘一男当年实体…

零基础学人工智能:TensorFlow 入门例子

识别手写图片 因为这个例子是 TensorFlow 官方的例子&#xff0c;不会说的太详细&#xff0c;会加入了一点个人的理解&#xff0c;因为TensorFlow提供了各种工具和库&#xff0c;帮助开发人员构建和训练基于神经网络的模型。TensorFlow 中最重要的概念是张量&#xff08;Tenso…

CA周记 - 用 Visual Studio Code 做基于 .NET MAUI 跨平台移动应用开发

自2010年以来&#xff0c;移动应用开发是非常热门的一个方向&#xff0c;从技术上我们经历了原生应用开发、基于 H5 的 Web App、混合模式的移动应用开发&#xff0c;再到跨平台移动应用开发。.NET 不仅是一个跨平台的应用&#xff0c;也是一个跨应用场景的平台。.NET的移动应用…

P2P网络穿越 NAT穿越

http://blog.csdn.net/mazidao2008/article/details/4933730 —————————————————————————————————————————————————————————————— 穿越NAT的意义&#xff1a; NAT是为了节省IP地址而设计的&#xff0c;但它隐藏了…

C#导入导出.CSV文件

欢迎您成为我的读者&#xff0c;希望这篇文章能给你一些帮助。前言大家好&#xff0c;我是阿辉。今天和大家一起来看看&#xff0c;C#在处理流文件时,我们最常用的导出Excel文件是如何操作的。在日常的业务编码过程中&#xff0c;很多时候需求就要求导出Office能打开的表格文件…

奋斗逼,真牛逼!

▲点击上方第二个findyi关注&#xff0c;回复“1”领取职场资料职场&认知洞察 丨 作者 / 易洋 这是findyi公众号的第304篇原创文章今天下午一个读者咨询我一个问题&#xff1a;这名读者感觉卷不过身边的加班狂人&#xff0c;但又感觉这些人丝毫不给公司创造价值&#xff0…

Entity Framework 批量插入

为什么80%的码农都做不了架构师&#xff1f;>>> 奋斗的小鸟——dogxuefeng Entity Framework 批量插入很慢 Entity Framework 批量插入很慢吗&#xff1f;我自己测试下 前几天看到一篇文章里提到过&#xff0c;在批量插入时&#xff0c;需要加上Context.Configur…

DEV-aspxgridview中的aspcheckbox

checkbox可以所以点击修改 例子演示&#xff1a;http://codecentral.devexpress.com/E2313/ 源程序&#xff1a;https://www.devexpress.com/Support/Center/Example/Details/E2313 表头可以全选所有的checkbook 具体演示如下&#xff1a;http://codecentral.devexpress.com/…

HDS业务定义永续IT架构

永续IT架构的出现并不是以取代原有设备为目的&#xff0c;而是帮助用户循序渐进地向新一代IT架构迁移。在HDS的手中&#xff0c;软件定义存储、对象存储等都成了保障业务永远在线的利器。技术创新固然可喜&#xff0c;但是最先进的技术不一定能直接带来企业收入的增加&#xff…

FreeBSD大败局

文 | 肖滢&lola策划 | lola出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013&#xff09;看过上一篇文章《还有人记得 Linux 之前&#xff0c;那个理想又骄傲的 BSD 吗&#xff1f;》的读者都知道&#xff0c; BSD 是 Unix 最重要的一个开源分支&#xff0c;这一本…

html拖放数据库字段,HTML5 拖放(Drag 和 Drop)

拖放是一种常见的特性&#xff0c;即抓取对象以后拖到另一个位置。在 HTML5 中&#xff0c;拖放是标准的一部分&#xff0c;任何元素都能够拖放.#div1 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}function allowDrop(ev){ev.preventDefault();}function…

谈谈 css 的各种居中——读编写高质量代码有感

css 的居中有水平居中和垂直居中&#xff0c;这两种居中又分为行内元素居中和块级元素居中&#xff0c;不同的居中用不同方法。 水平居中 1、行内元素水平居中&#xff08;文本&#xff0c;图片&#xff09; 给父层设置 text-align:center; 可以实现行内元素水平居中。 <!DO…

.NET遗留应用改造——性能优化篇

由于各种原因我们总是要与公司各种老项目打交道。天有不测风云&#xff0c;谁也不知道这坨屎山会从哪个方向把你的嘴塞的满满的&#xff0c;还不让你吐出来。既然如此...那只能细嚼慢咽的吞下去吧。说实在话&#xff0c;只要业务不死&#xff0c;那些老大伯项目就还有价值。更何…

华为西安工业大学鸿蒙,培养百位将领、19位院士,这所211大学被誉为“华为人的母校”...

在社会上&#xff0c;985工程重点大学认可度是普遍要比211工程大学高的&#xff0c;并且985工程大学实力也比较强。但比较例外的是&#xff0c;华为这个让国人骄傲的企业&#xff0c;对一个211工程大学青睐程度却超过了绝大部分985工程大学&#xff0c;这所211大学甚至还被誉为…

Android Studio之Instant Run requires ‘Tools | Android | Enable ADB integration‘ to be enabled解决办法

1、问题 Android studio运行项目时候出现这个提示 Instant Run requires Tools | Android | Enable ADB integration to be enabled 2、原因 由于新版本中的Instant Run &#xff08;即时运行&#xff09;引起的 官方介绍 即使运行 https://developer.android.com/studio/r…

C# 11 预览,又增加了实用的语法糖

文 | 罗奇奇出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013&#xff09;.NET 首席项目经理凯瑟琳在博客中介绍了 C# 11 的一些预览性新功能&#xff0c;这些功能可以在 Visual Studio 17.1 和 .NET SDK 6.0.200 中体验&#xff0c;下面摘录一部分新特性作介绍&#…