首页 > 编程语言 >ASP.NET Core中如何对不同类型的用户进行区别限流

ASP.NET Core中如何对不同类型的用户进行区别限流

时间:2024-09-19 16:15:09浏览次数:7  
标签:Core ASP 中间件 用户 限流 context new Id

老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次。

这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比较,超过指定的数字就返回错误。

嗯,原理就是这么简单。不过真正写起来还要考虑更多问题:

  • 统计数据的数据结构是什么样的?字典 or 行记录?
  • 统计数据记录到哪里?内存 or MySQL or Redis?
  • 分布式应用怎么精确计数?分布式锁 or 队列 or 事务?
  • 吞吐量比较大时如何扛得住?内存 or Redis or 数据库集群?
  • 这些数据要一直保留吗?自动过期 or 定期清理?
  • 如何返回错误?自定义错误 or HTTP标准错误码?

自己去做这些事还是有点麻烦的,这里介绍一个ASP.NET Core的中间件来满足这个限流需求:FireflySoft.RateLimit.AspNetCore。使用步骤如下:


 

1、安装Nuget包

已经发布到nuget.org,有多种安装方式,选择自己喜欢的就行了。

包管理器命令:

Install-Package FireflySoft.RateLimit.AspNetCore

或者.NET命令:

dotnet add package FireflySoft.RateLimit.AspNetCore

或者项目文件直接添加:

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

 

2、使用中间件

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

复制代码
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    app.UseRateLimit(new RateLimitProcessor<HttpContext>.Builder()
        .WithAlgorithm(new FixedWindowAlgorithm<HttpContext>( new[] {
            new FixedWindowRateLimitRule<HttpContext>()
            {
                Id = "1",
                ExtractTarget = context =>
                {
                    // 这里假设用户Id是从cookie中传过来的,需根据实际情况获取
                    return context.Request.GetTypedHeaders().Get<string>("userId");
                },
                CheckRuleMatching = context =>
                {
                    // 这里假设用户类型是从cookie中传过来的,实际可能需要根据用户Id再去查询
                    // 0免费用户 1收费用户
                    int userType = context.Request.GetTypedHeaders().Get<int>("userType");
                    if(userType==0){
                        return true;
                    }
                    return false;
                },
                Name="免费用户限流规则",
                LimitNumber=100,
                StatWindow=TimeSpan.FromDays(1)
            },
            new FixedWindowRateLimitRule<HttpContext>()
            {
                Id = "2",
                ExtractTarget = context =>
                {
                    // 这里假设用户Id是从cookie中传过来的,需根据实际情况获取
                    return context.Request.GetTypedHeaders().Get<string>("userId");
                },
                CheckRuleMatching = context =>
                {
                    // 这里假设用户类型是从cookie中传过来的,实际可能需要根据用户Id再去查询
                    // 0免费用户 1收费用户
                    int userType = context.Request.GetTypedHeaders().Get<int>("userType");
                    if(userType==1){
                        return true;
                    }
                    return false;
                },
                Name="收费用户限流规则",
                LimitNumber=1000000,
                StatWindow=TimeSpan.FromDays(1)
            }
        }))
        .WithError(new Core.RateLimitError()
        {
            Code=429,
            Message = "查询数达到当天最大限制"
        })
        //.WithStorage(new RedisStorage(StackExchange.Redis.ConnectionMultiplexer.Connect("localhost")))
        .Build());

    ...
}
复制代码

 

使用此中间件需要构建一个名为RateLimitProcessor的限流处理器实例,指定限流处理的请求类型HttpContext,设置限流处理的三个方面:

限流使用的算法以及对应的规则

限流算法,根据这个需求使用固定窗口算法就可以了,也称为计数器算法。此中间件还提供了滑动窗口算法、漏桶算法、令牌桶算法,可以根据需要选择。

不同的限流算法有不同的限流规则类型,在这里使用的是固定窗口限流规则,针对免费用户和收费用户分别定义了两个规则,注意其中的几个参数:

  • Id:在当前的版本中Id必须手动指定,并且不能重复。
  • ExtractTarget:传递一个方法用于从请求中提取限流目标,这里就是用户Id。
  • CheckRuleMatching传递一个方法用于检查当前请求是否适用当前规则,这里根据用户类型进行判断。
  • StatWindow是固定窗口的大小,是一个时间跨度,这里是1天。
  • LimitNumber是限流值,在StatWindow时间内请求数超过它就会触发限流。

这里有两个比较有意思的设置:ExtractTarget和CheckRuleMatching,他们共同作用,让用户可以完全自由的定制自己限流的目标和条件,无论是IP、ClientId或者Url。

限流统计数据的持久化方式

FireflySoft.RateLimit中的限流计数目前支持保存在内存或者Redis中,也可以通过实现IRateLimitStorage来定义一个新的存储器,不设置时默认为内存存储。

对于只需要部署一份的程序,绝大部分情况下使用内存就够了;但是如果限流的时间窗口比较长,比如1小时限制300次,重启就会丢失计数,这可能是个风险,此时使用Redis会比较合适。对于分布式应用,也建议使用Redis存储。

限流统计数据会根据限流时间窗口自动过期移除。

被限流时的错误码和消息

默认限流错误Code是429,这个会作为HttpStatusCode返回;Message默认为null,你可以修改为自己的任意文字提示,这个会作为Http Body的内容返回。


 

以上就是使用FireflySoft.RateLimit.AspNetCore对不同类型的用户进行区别限流的使用方法。

如果觉得还是限制的有点死,比如返回错误信息部分,想返回一个json格式的错误消息,还可以使用FireflySoft.RateLimit.Core这个包来封装自己的ASP.NET Core中间件。

标签:Core,ASP,中间件,用户,限流,context,new,Id
From: https://www.cnblogs.com/ILoveJackSparrow/p/18420826

相关文章

  • 限流器的实践
    背景我们有一个业务场景是给学生发布考试,发布的过程不复杂,就是一个老师传递一些考试相关的参数过来,服务器自动给所有学生生成一份任务,但是在学生上交的时候会有个问题,就是成百上千的学生一起上交,会有并发流量的问题。这里由于我们的考试可能会设计多个班级的联考,乃至一个学校或......
  • 易优eyoucms网站报错 \core\library\think\App.php Fatal error: Call to undefin
    当你遇到 Fatalerror:Calltoundefinedfunctionthink\switch_citysite() 这样的错误时,说明在代码中调用了一个未定义的函数 think\switch_citysite()。这种情况通常是因为函数没有被正确地引入或者该函数根本不存在于当前的代码库中。解决方案确认函数的存在检查 s......
  • 易优eyoucms网站详情页报错报错 \core\library\think\Loader.php 类不存在:app\co
    类不存在:app\common\model\Pic,这个错误表明PHP无法找到类 app\common\model\Pic。这通常是因为类文件未被正确加载或命名空间配置不正确导致的。以下是一些可能的解决步骤:1.确认类文件路径确保类文件 Pic 的路径正确并且文件存在。检查文件路径确认 app\common\model......
  • 易优eyoucms网站报错,\\core\\library\\think\\db\\Connection.php
     报错\\\\core\\\\library\\\\think\\\\db\\\\Connection.php第380行左右数据表或视图不存在,请联系技术处理。[错误代码]SQLSTATE[42S02]:Basetableorviewnotfound:1146Table'eyoucms.ey_channeltype'doesn'texist根据提供的错误信息 SQLSTATE[42S02]:......
  • 易优eyoucms网站报错 \core\library\think\db\Connection.php 第 307 行左右,SQLS
    根据提供的错误信息 SQLSTATE[HY000][1045]Accessdeniedforuser'cs2021'@'localhost'(usingpassword:YES),这个错误表明数据库访问被拒绝了,通常是因为用户名或密码不正确导致的。以下是几个可能的解决步骤:检查数据库连接配置:确认数据库连接配置文件中的用户名和密......
  • 易优eyoucms网站报错 /core/library/think/db/Connection.php 第 389 行左右,如何解决?
    SQLSTATE[42S22]:Columnnotfound:1054Unknowncolumn'groupid'in'whereclause'遇到“SQLSTATE[42S22]:Columnnotfound:1054Unknowncolumn'groupid'in'whereclause'”这类错误,通常是因为数据库表结构与代码中的查询不匹配。具体来说,可能是数据库表中缺少某个列......
  • DevExpress中文教程:如何将WinForms数据网格连接到ASP. NET Core WebAPI服务?
    日前DevExpress官方发布了DevExpressWinForms的后续版本——将.NET桌面客户端连接到安全后端WebAPI服务(EFCorewithOData),在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpressWinForms数据网格。P.S:DevExpressWinForms拥有180+组件和UI库,能为WindowsForms......
  • 易优cms错误\core\library\think\db\Connection.php解决
    当您在使用易优CMS时遇到core\library\think\db\Connection.php相关的错误,这通常意味着数据库连接或操作方面出现了问题。这类错误可能由多种因素引起,包括但不限于数据库连接问题、表结构问题、数据库迁移问题等。常见错误示例数据表或视图不存在:这通常表明数据库中缺少某些表......
  • .NET Standard/.NET Framework/.NET Core/ASP.NET/ASP.NET Core/ASP.NET MVC/ADO.NET
    这是常识.......就算名字取得再混乱名字角色简介.NETStandard规范一种跨平台的API规范,它定义了一组共同的类库和框架特性.NETFramework框架 Windows 平台的框架.NETCore框架开源、跨平台的框架ASP.NET框架在.NETFramework上构建的,专注于传统的Web服务器端开发ASP.NET......
  • 当前标识(IIS APPPOOL\.NET v4.5)没有对“C:\Windows\Microsoft.NET\Framework64
    当前标识(IISAPPPOOL\.NETv4.5)没有对“C:\Windows\Microsoft.NET\Framework64\v4.0.30319\TemporaryASP.NETFiles”的写访问权限。初学者在使用ISS创建网站时是不是也遇到过类似的问题,这可能是执行当前Web请求期间生成了未经处理的异常,主要就是设置对TemporaryASP.NE......