前言

最近一直在忙(2月份沉迷steam,3月开始工作各种忙),好久没更新博客了,不过也积累了一些,忙里偷闲记录一下。

这个需求是这样的,我之前做了个工单系统,现在要对登录、注册、发起工单这些功能做限流,不能让用户请求太频繁。

从 .Net7 开始,已经有内置的限流功能了,但目前我们的项目还在使用 .Net6 LTS 版本,下一个 LTS 没发布之前,暂时不考虑使用 .Net7 这种非 LTS 版本。

然后我找到了这个 AspNetCoreRateLimit 组件,在 Github 上有接近三千个星星,看了一下文档使用也简单灵活,于是决定尝试一下~

AspNetCoreRateLimit 组件

项目主页: https://github.com/stefanprodan/AspNetCoreRateLimit

这是官方的介绍:

AspNetCoreRateLimit is an ASP.NET Core rate limiting solution designed to control the rate of requests that clients can make to a Web API or MVC app based on IP address or client ID.

The AspNetCoreRateLimit NuGet package contains an IpRateLimitMiddleware and a ClientRateLimitMiddleware, with each middleware you can set multiple limits for different scenarios like allowing an IP or Client to make a maximum number of calls in a time interval like per second, 15 minutes, etc. You can define these limits to address all requests made to an API or you can scope the limits to each API URL or HTTP verb and path.

用最近很厉害的 ChatGPT 翻译一下:

AspNetCoreRateLimit是一个ASP.NET Core速率限制解决方案,旨在基于IP地址或客户端ID控制客户端对Web API或MVC应用程序发出请求的速率。

AspNetCoreRateLimit NuGet包 包含一个IpRateLimitMiddleware和一个ClientRateLimitMiddleware,每个中间件都可以为不同的场景设置多个限制,比如允许IP或客户端在时间间隔内进行最大数量的调用,比如每秒、15分钟等。您可以定义这些限制以处理对API发出的所有请求,也可以将限制范围限定为每个API URL或HTTP动词和路径。

这个组件使用起来挺灵活的,直接在 AspNetCore配置 里定义规则,意味着可以不重新编译程序就修改限流规则,官方给的例子是直接在 appsettings.json 里配置,但使用其他配置源理论上也没问题(配置中心用起来)。

简单介绍下这个组件的思路

首先它有两种模式:

  • 根据IP地址限流
  • 根据 ClientID 限流

IP地址很容易理解,ClientID 我一开始以为是用户ID,不过看了说明,是一个放在请求头里的参数,比如 X-ClientId,这个要自己实现,可以直接用用户ID。

为了方便使用,我这个项目里面直接用IP地址模式。

RateLimit 组件可以配置全局的限流,也可以配置对某个IP地址(段)进行限流。

配置服务

为了从 appsettings.json 读取数据,先在 Program.cs 注册配置服务

builder.Services.AddOptions();

然后写个扩展方法来注册 RateLimit 的相关服务

引入命名空间

using AspNetCoreRateLimit;
using AspNetCoreRateLimit.Redis;
using StackExchange.Redis;

写个静态类

public static class ConfigureRateLimit {
public static void AddRateLimit(this IServiceCollection services, IConfiguration conf) {
//load general configuration from appsettings.json
services.Configure<IpRateLimitOptions>(conf.GetSection("IpRateLimiting")); var redisOptions = ConfigurationOptions.Parse(conf.GetConnectionString("Redis"));
services.AddSingleton<IConnectionMultiplexer>(provider => ConnectionMultiplexer.Connect(redisOptions));
services.AddRedisRateLimiting(); services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
} public static IApplicationBuilder UseRateLimit(this IApplicationBuilder app) {
app.UseIpRateLimiting(); return app;
}
}

来解析一下配置的代码。

我暂时不需要对不同的IP地址段应用不同的限流规则

所以直接用 IpRateLimitOptions

services.Configure<IpRateLimitOptions>(conf.GetSection("IpRateLimiting"));

要做根据IP限流,就得记录每个IP访问了多少次,RateLimit 组件支持多种存储方式,最简单的可以直接存内存里,不过为了稳定我还是选择 Redis。

这几行代码就是配置 Redis 的。

var redisOptions = ConfigurationOptions.Parse(conf.GetConnectionString("Redis"));
services.AddSingleton<IConnectionMultiplexer>(provider => ConnectionMultiplexer.Connect(redisOptions));
services.AddRedisRateLimiting();

最后注入一下 IRateLimitConfiguration,我猜应该是中间件要用到的。至少我目前在 Controller 代码里不需要用到任何跟 RateLimit 有关的代码。

写完了扩展方法,回到 Program.cs

注册服务

builder.Services.AddRateLimit(builder.Configuration);

添加中间件

var app = builder.Build();

app.UseExceptionless();
app.UseStaticFiles(new StaticFileOptions {
ServeUnknownFileTypes = true
});
app.UseRateLimit(); // ... app.Run();

我这里把 UseRateLimit 放在 UseStaticFiles 后面,不然页面里的静态文件都被算进去访问次数,很快就被限流了。

配置

appsettings.json 里写具体的限流规则。

官网提供的配置规则不能照抄,要理解一下他的文档

  • EnableEndpointRateLimiting - 这个选项要设置为 true ,不然设置的限流是全局的,不能根据某个路径单独设置限流
  • StackBlockedRequests - 按照默认的设置为 false 就行,设置成 true 的话,一个接口被限流之后再重复请求还会计算到访问次数里面,这样有可能导致限流到天荒地老。

其他的配置顾名思义,懂的都懂。

GeneralRules 是对具体路径的限流规则

如果全局限流,把 EnableEndpointRateLimiting 设置为 false 的话,那就这样设置,1分钟只能访问5次

{
"Endpoint": "*",
"Period": "1m",
"Limit": 5
}

Endpoint 可以设置 HTTP方法:路径 的形式,比如 post:/account/login 具体看文档吧(参考文档第三条)

附上我的配置文件,对添加工单、登录、注册接口进行限流。

{
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"IpWhitelist": [],
"EndpointWhitelist": [
"get:/api/license",
"*:/api/status"
],
"ClientWhitelist": [
"dev-id-1",
"dev-id-2"
],
"GeneralRules": [
{
"Endpoint": "*:/ticket/add",
"Period": "1m",
"Limit": 5
},
{
"Endpoint": "post:/account/login",
"Period": "1m",
"Limit": 5
},
{
"Endpoint": "post:/account/SignUp",
"Period": "1m",
"Limit": 5
}
],
"QuotaExceededResponse": {
"Content": "{{ \"message\": \"先别急,你访问得太快了!\", \"details\": \"已经触发限流。限流规则: 每 {1} 只能访问 {0} 次。请 {2} 秒后再重试。\" }}",
"ContentType": "application/json",
"StatusCode": 429
}
}
}

同时自定义了被限流时的提示。

效果如下

{
"message": "先别急,你访问得太快了!",
"details": "已经触发限流。限流规则: 每 1m 只能访问 5 次。请 16 秒后再重试。"
}

参考资料

Asp-Net-Core开发笔记:使用RateLimit中间件实现接口限流的更多相关文章

  1. ASP.NET Core 开发-中间件(Middleware)

    ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...

  2. ASP.NET Core 开发-中间件(StaticFiles)使用

    ASP.NET Core 开发,中间件(StaticFiles)的使用,我们开发一款简易的静态文件服务器. 告别需要使用文件,又需要安装一个web服务器.现在随时随地打开程序即可使用,跨平台,方便快捷 ...

  3. 在CentOS7 开发与部署 asp.net core app笔记

    原文:在CentOS7 开发与部署 asp.net core app笔记 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/lihongzhai/art ...

  4. [ASP.NET Core开发实战]基础篇03 中间件

    什么是中间件 中间件是一种装配到应用管道,以处理请求和响应的组件.每个中间件: 选择是否将请求传递到管道中的下一个中间件. 可在管道中的下一个中间件前后执行. ASP.NET Core请求管道包含一系 ...

  5. ASP.Net Core开发(踩坑)指南

    ASP.NET与ASP.NET Core很类似,但它们之间存在一些细微区别以及ASP.NET Core中新增特性的使用方法,在此之前也写过一篇简单的对比文章ASP.NET MVC应用迁移到ASP.NE ...

  6. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  7. asp.net core开发注意事项

    1.类库的创建尽量选择.net standard. 如果选择.net core 则.net framework不能调用该类库, .net core和.net framework都可以调用.net st ...

  8. ASP.NET Core 开发人员异常页面

    UseDeveloperExceptionPage 中间件 我们谈谈在 Startup 类的 Configure()方法中以下代码: public void Configure(IApplicatio ...

  9. 2月送书福利:ASP.NET Core开发实战

    大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...

  10. [ASP.NET Core开发实战]开篇词

    前言 本系列课程文章主要是学习官方文档,再输出自己学习心得,希望对你有所帮助. 课程大纲 本系列课程主要分为三个部分:基础篇.实战篇和部署篇. 希望通过本系列课程,能让大家初步掌握使用ASP.NET ...

随机推荐

  1. vue验证码倒计时60s

    vue3验证码倒计时60s //倒计时60s const timeNum = ref(60); const countDown = ref(); const isShowSend = ref(true ...

  2. calibredrv 对layer做操作

    #clip.tclset L [layout create xxx.gds] $L create layer 10.0 $L create polygon 10.0 10 1000 1000 2000 ...

  3. 如何避免reblance

    reblance是什么? 什么时候会发生rebalnce? 如何尽量避免这些情况? 若不可避免的要发生reblance?怎么尽量减少影响? reblance是什么? Reblance是Kafka协调者 ...

  4. 解决未定义的count键“报错为:"Uncaught ReferenceError: count is not defined"

    报错: 源码:Vuex仓库.js let state = {     count } export default state   解决:未赋值的count键

  5. 使用cpu-z简单看处理器,显卡等

    心血来潮想了解一下自己的电脑.在网上搜索cpu-z,大小只有几百kb.下面以我自己电脑为例,上图: 某些地方我也不是很了解,不太了解的我就直接跳过了.在网上查阅相关资料后,有下面的认识: (1)处理器 ...

  6. vue安装与卸载

    一.安装最新版本 npm install -g @vue/cli 或 yarn global remove vue-cli 查看版本 vue --version 或 vue -V 二.vue-cli( ...

  7. springboot配置类@ConfigurationProperties报错Not registered via @EnableConfigurationProperties or marked as Spring component

    添加一个@Component可以解决此问题,只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能.

  8. JAVA 、Http协议:

    JAVA如何配置服务器: Http协议: 1.什么是Http协议 HTTP,超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的   一种网络协议.所有的W ...

  9. STL练习-看病要排队

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1873   看病要排队这个是地球人都知道的常识. 不过经过细心的0068的观察,他发现了医院里排队还是有讲究的 ...

  10. Javaheima12

    Java 不可变集合 如果某个数据不能修改,把它防御性地拷贝到不可变集合红是个很好的实践 或者当集合对象被不可信的库调用时,不可变形式是安全的 创建 再List,Set,Map接口中,都存在of方法, ...