ASP.NET Core 中的速率限制中间件的使用

news/2025/3/10 15:51:17/文章来源:https://www.cnblogs.com/netcore5/p/18635522

简介

在ASP.NET Core中,速率限制中间件是用来控制客户端对Web API或MVC应用程序发出请求的速率,以防止服务器过载和提高安全性。

下面是 AddRateLimiter 的一些基本用法:

1. 注册服务

Startup.csProgram.cs 中,需要注册 AddRateLimiter 服务。这可以通过以下代码完成:

builder.Services.AddRateLimiter(options =>
{// 配置速率限制选项
});

2. 添加速率限制策略

可以添加不同类型的速率限制策略, 包括固定窗口、滑动窗口、令牌桶和并发限制。

固定窗口限制器(Fixed Window Limiter)

固定窗口限制器使用固定的时间窗口来限制请求。当时间窗口到期后,会开始一个新的时间窗口,并重置请求限制。例如,可以设置一个策略,允许每个12秒的时间窗口内最多4个请求。

builder.Services.AddRateLimiter(options =>
{options.AddFixedWindowLimiter("fixed", opt =>{opt.Window = TimeSpan.FromMinutes(1); // 时间窗口opt.PermitLimit = 3; // 在时间窗口内允许的最大请求数opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; // 请求处理顺序opt.QueueLimit = 2; // 队列中允许的最大请求数});
});
app.UseRateLimiter();

即固定时间请求的次数,超过次数就会限流,下一个窗口时间将次数重置

经过测试,多余的请求还是会等待

https://www.cnblogs.com/guoxiaotian/p/17834892.html

滑动窗口限制器(Sliding Window Limiter)

滑动窗口算法:

  • 与固定窗口限制器类似,但为每个窗口添加了段。 窗口在每个段间隔滑动一段。 段间隔的计算方式是:(窗口时间)/(每个窗口的段数)。
  • 将窗口的请求数限制为 permitLimit 个请求。
  • 每个时间窗口划分为一个窗口 n 个段。
  • 从倒退一个窗口的过期时间段(当前段之前的 n 个段)获取的请求会添加到当前的段。 我们将倒退一个窗口最近过期时间段称为“过期的段”。

请考虑下表,其中显示了一个滑动窗口限制器,该限制器的窗口为 30 秒、每个窗口有三个段,且请求数限制为 100 个:

  • 第一行和第一列显示时间段。
  • 第二行显示剩余的可用请求数。 其余请求数的计算方式为可用请求数减去处理的请求数和回收的请求数。
  • 每次的请求数沿着蓝色对角线移动。
  • 从时间 30 开始,从过期时间段获得的请求会再次添加到请求数限制中,如红色线条所示。

下表换了一种格式来显示上图中的数据。 “可用”列显示上一个段中可用的请求数(来自上一个行中的“结转”)。 第一行显示有 100 个可用请求,因为没有上一个段。

时间 可用 获取的请求数 从过期段回收的请求数 结存请求数
0 100 20 0 80
10 80 30 0 50
20 50 40 0 10
30 10 30 20 0
40 0 10 30 20
50 20 10 40 50
60 50 35 30 45
 services.AddRateLimiter(options =>{options.AddSlidingWindowLimiter("sliding", opt =>{opt.Window = TimeSpan.FromMinutes(1); // 总窗口时间为1分钟opt.SegmentsPerWindow = 6; // 将1分钟的窗口分为6个段,即每10秒一个段opt.PermitLimit = 10; // 整个窗口时间内允许的最大请求数});});

令牌桶限制器(Token Bucket Limiter)

令牌桶限制器维护一个滚动累积的使用预算,作为一个令牌的余额。它以一定的速率添加令牌,当服务请求发生时,服务尝试提取一个令牌(减少令牌计数)来满足请求。如果没有令牌,服务就达到了限制,响应被阻塞。

    services.AddRateLimiter(configureOptions =>{configureOptions.AddTokenBucketLimiter("token-bucket", options =>{options.TokenLimit = 100; // 桶的容量options.ReplenishmentPeriod = TimeSpan.FromSeconds(10); // 补充周期,即每10秒补充一次令牌options.TokensPerPeriod = 10; // 每个周期补充的令牌数options.AutoReplenishment = true; // 是否自动补充令牌options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; // 队列处理顺序options.QueueLimit = 10; // 请求队列长度限制});});

并发限制器(Concurrency Limiter)

并发限制器是最简单的速率限制形式。它不关注时间,只关注并发请求的数量。

    services.AddRateLimiter(options =>{options.AddConcurrencyLimiter("concurrency", options =>{options.PermitLimit = 1; // 最大并发请求数options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; // 队列处理顺序options.QueueLimit = 10; // 请求队列长度限制});});

3. 使用中间件

Configure 方法或 Program.cs 中,需要使用 UseRateLimiter 中间件:

app.UseRateLimiter();

4. 应用速率限制策略

可以全局应用速率限制策略,或者将其应用于特定的控制器或动作:

全局配置

app.MapControllers().RequireRateLimiting("fixed");

应用于特定的控制器

[EnableRateLimiting("fixed")]
public class RateLimitTestController : ControllerBase
{// 控制器动作
}

应用于特定的动作

[EnableRateLimiting("fixed")]
public async Task<IActionResult> Get()
{// 动作逻辑
}

5. 禁用速率限制

也可以选择禁用速率限制,无论是在控制器级别还是特定动作级别:

禁用控制器级别的速率限制

[DisableRateLimiting]
public class RateLimitTestController : ControllerBase
{// 控制器动作
}

禁用特定动作的速率限制

[DisableRateLimiting]
public async Task<IActionResult> Get()
{// 动作逻辑
}

自定义响应

当客户端超出速率限制时,可以自定义响应。例如,可以设置OnRejected回调来自定义响应:

options.OnRejected = (context, token) =>
{context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;context.HttpContext.Response.Headers["Retry-After"] = "60"; // 建议60秒后重试context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.", cancellationToken: token);return Task.CompletedTask;
};

总结

在ASP.NET Core应用程序中实现有效的速率限制策略,以保护的API免受滥用和过载。欢迎关注我的公众号:Net分享

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

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

相关文章

java 使用HttpClient发送@RequestBody类型的请求(解决中文乱码)

如何使用java发送参数以@RequestBody类型接收到的请求。如下使用java的HttpClient写一个样例 依赖<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.10</version> </dep…

再战博客园美化(五)

再战系列更新到几来着。。。 (看一眼)哦,原来更新到五了! 这一次,我直接来个连接到本机,在线调试!好了,似了。 https是什么东西,我有吗? csdn启动真的假的,自签名还能过系统,这是拿了管理员权限? https://xiaoshen.blog.csdn.net/article/details/135893188我就知…

CDS标准视图:设备信息 I_EquipmentData

视图名称:I_EquipmentData 视图类型:基础视图 视图代码:点击查看代码 @EndUserText.label: Equipment Data @VDM.viewType: #COMPOSITE @AbapCatalog.sqlViewName: IEQUIPMENTATTR @AbapCatalog.compiler.compareFilter: true @ClientHandling.algorithm: #SESSION_VARIABLE…

四款简洁又好用的日记app推荐

以前使用纸质的笔记本来写日记,但是最近几年再也没有写过日记了,最近又想要开始写日记,发现用日记本app会更加简单方便。 打开手机就能给直接记录,除了记录文字,还可以保存图片、语音、视频等,更加简单便捷! 1、念念手帐 优点:画风可爱,很适合喜欢可爱风格的女生。可以…

polarctf-crypto困难难度wp整理(截止至2024.12)

分段解密 加密脚本如下: import sysdef abc(First): First = c_uint32(First)return Firstdef enflag(i, j):a = 32tt = 0x9e3779b9b = [0,0]First = abc(i[0])Second = abc(i[1])add = abc(0)add=add.valuewhile(a>0):add += ttFirst.value += ( Second.value << 4…

我的第一篇博客!学习Markdown

Markdown学习 标题 (#[空格]+标题名字) 二级标题##[空格]+标题名字 三级标题###[空格]+标题名字 以此类推,最高六级; 字体 Hello,World! (两边加两个星号"**"为设置粗体); Hello,World! (两边加一个星号"*"为设置斜体); Hello,World! (两边加三个星号“**…

Python包管理不再头疼:uv工具快速上手

Python 包管理生态中存在多种工具,如 pip、pip-tools、poetry、conda 等,各自具备一定功能。 而今天介绍的uv 是 Astral 公司推出的一款基于 Rust 编写的 Python 包管理工具,旨在成为 “Python 的 Cargo”。 它提供了快速、可靠且易用的包管理体验,在性能、兼容性和功能上都…

博客园markdown及配图自动上传配置

解决自己使用markdown写博客,上传到博客园上面,需要一张一张重新上传图片的问题博客园markdown与配图自动上传配置(mac版 m芯片)引言 安装配置工具 尾注前言 目的:因为自己使用markdown写博客,但是在博客园上面发布的时候,发现本地写好的markdown文件,上传到博客园上面…

【unity】学习制作类银河恶魔城游戏-4-

制作攻击计数器给全部攻击动作应用帧事件但是理想情况下应该是,短间隔时间内连续点击鼠标才能连击,加入连击计时器编辑代码修补“桶子” 解决攻击时移动的问题解决冲刺时攻击的问题解决无方向键输入时原地冲刺的问题解决空中攻击无法掉落的问题继承“inheritance”(继承)是…

React 移动端框架

1. Material-UI Material-UI 组件是独立工作的。 它们是自我支持的,并只要注入而且仅注入它们需要显示的样式。 他们不依赖任何全局的样式表,如 normalize.css。Material-UI首先是移动开发的,我们首先为移动设备编写代码,然后根据需要使用CSS媒体查询扩展组件。 要确保所有…

hbuilder 调试跨域问题解决方案

放到 system.webServer 节点下 web.config<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Headers" value="Content-Type" /> <…