百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Asp.NET Core 限流控制

yuyutoo 2024-12-03 19:36 3 浏览 0 评论

起因:

 近期项目中,提供了一些调用频率较高的api接口,需要保障服务器的稳定运行;需要对提供的接口进行限流控制。避免因客户端频繁的请求导致服务器的压力。

一、AspNetCoreRateLimit 介绍

 AspNetCoreRateLimit是一个ASP.NET Core速率限制的解决方案,旨在控制客户端根据IP地址或客户端ID向Web API或MVC应用发出的请求的速率。AspNetCoreRateLimit包含一个IpRateLimitMiddlewareClientRateLimitMiddleware,每个中间件可以根据不同的场景配置限制允许IP或客户端,自定义这些限制策略,也可以将限制策略应用在每?个API URL或具体的HTTP Method上。

二、AspNetCoreRateLimit使用

 由上面介绍可知AspNetCoreRateLimit支持了两种方式:基于客户端IP(IpRateLimitMiddleware)和客户端ID(ClientRateLimitMiddleware)速率限制 接下来就分别说明使用方式

 添加Nuget包引用:

 Install-Package AspNetCoreRateLimit 
  • 基于客户端IP速率限制

  1、修改Startup.cs中方法:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        //需要从加载配置文件appsettings.json
        services.AddOptions();
        //需要存储速率限制计算器和ip规则
        services.AddMemoryCache();

        //从appsettings.json中加载常规配置,IpRateLimiting与配置文件中节点对应
        services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));

        //从appsettings.json中加载Ip规则
        services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));

        //注入计数器和规则存储
        services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
        services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

        services.AddControllers();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        //配置(解析器、计数器密钥生成器)
        services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();

        //Other Code
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //Other Code

        app.UseRouting();

        app.UseAuthorization();
     //启用客户端IP限制速率
        app.UseIpRateLimiting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

  2、在appsettings.json中添加通用配置项节点:(IpRateLimiting节点与Startup中取的节点对应)

"IpRateLimiting": {
  //false,则全局将应用限制,并且仅应用具有作为端点的规则*。例如,如果您设置每秒5次调用的限制,则对任何端点的任何HTTP调用都将计入该限制
  //true, 则限制将应用于每个端点,如{HTTP_Verb}{PATH}。例如,如果您为*:/api/values客户端设置每秒5个呼叫的限制,
  "EnableEndpointRateLimiting": false,
  //false,拒绝的API调用不会添加到调用次数计数器上;如 客户端每秒发出3个请求并且您设置了每秒一个调用的限制,则每分钟或每天计数器等其他限制将仅记录第一个调用,即成功的API调用。如果您希望被拒绝的API调用计入其他时间的显示(分钟,小时等)
  //,则必须设置StackBlockedRequests为true。
  "StackBlockedRequests": false,
  //Kestrel 服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IP X-Real-IP使用此选项来设置
  "RealIpHeader": "X-Real-IP",
  //取白名单的客户端ID。如果此标头中存在客户端ID并且与ClientWhitelist中指定的值匹配,则不应用速率限制。
  "ClientIdHeader": "X-ClientId",
  //限制状态码
  "HttpStatusCode": 429,
  ////IP白名单:支持Ip v4和v6 
  //"IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],
  ////端点白名单
  //"EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
  ////客户端白名单
  //"ClientWhitelist": [ "dev-id-1", "dev-id-2" ],
  //通用规则
  "GeneralRules": [
    {
      //端点路径
      "Endpoint": "*",
      //时间段,格式:{数字}{单位};可使用单位:s, m, h, d
      "Period": "1s",
      //限制
      "Limit": 2
    },
   //15分钟只能调用100次
    {"Endpoint": "*","Period": "15m","Limit": 100},
   //12H只能调用1000
    {"Endpoint": "*","Period": "12h","Limit": 1000},
   //7天只能调用10000次
    {"Endpoint": "*","Period": "7d","Limit": 10000}
  ]
}

  配置节点已添加相应注释信息。

   规则设置格式:   

端点格式:{HTTP_Verb}:{PATH},您可以使用asterix符号来定位任何HTTP谓词。

期间格式:{INT}{PERIOD_TYPE},您可以使用以下期间类型之一:s, m, h, d。

限制格式:{LONG}

  3、特点Ip限制规则设置,在appsettings.json中添加 IP规则配置节点

"IpRateLimitPolicies": {
  //ip规则
  "IpRules": [
    {
      //IP
      "Ip": "84.247.85.224",
      //规则内容
      "Rules": [
        //1s请求10次
        {"Endpoint": "*","Period": "1s","Limit": 10},
        //15分钟请求200次
        {"Endpoint": "*","Period": "15m","Limit": 200}
      ]
    },
    {
      //ip支持设置多个
      "Ip": "192.168.3.22/25",
      "Rules": [
        //1秒请求5次
        {"Endpoint": "*","Period": "1s","Limit": 5},
        //15分钟请求150次
        {"Endpoint": "*","Period": "15m","Limit": 150},
        //12小时请求500次
        {"Endpoint": "*","Period": "12h","Limit": 500}
      ]
    }
  ]
}
  • 基于客户端ID速率限制

  1、修改Startup文件:

public void ConfigureServices(IServiceCollection services)
{
    //需要从加载配置文件appsettings.json
    services.AddOptions();

    //需要存储速率限制计算器和ip规则
    services.AddMemoryCache();

    //从appsettings.json中加载常规配置
    services.Configure<ClientRateLimitOptions>(Configuration.GetSection("IPRateLimiting"));

    //从appsettings.json中加载客户端规则
    services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("ClientRateLimitPolicies"));

    //注入计数器和规则存储
    services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
    services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

    
    services.AddControllers();

        // https://github.com/aspnet/Hosting/issues/793
        // the IHttpContextAccessor service is not registered by default.
        //注入计数器和规则存储
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        //配置(解析器、计数器密钥生成器)
        services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
        //启用客户端限制
    app.UseClientRateLimiting();

    app.UseMvc();
}

  2、通用配置采用IP限制相同配置,添加客户端限制配置:

//客户端限制设置
"ClientRateLimitPolicies": {
  "ClientRules": [
    {
      //客户端id
      "ClientId": "client-id-1",
      "Rules": [
        {"Endpoint": "*","Period": "1s","Limit": 10},
        {"Endpoint": "*","Period": "15m","Limit": 200}
      ]
    },
    {
      "ClientId": "client-id-2",
      "Rules": [
        {"Endpoint": "*","Period": "1s","Limit": 5},
        {"Endpoint": "*","Period": "15m","Limit": 150},
        {"Endpoint": "*","Period": "12h","Limit": 500}
      ]
    }
  ]
}

  3、调用结果:

    设置规则:1s只能调用一次:首次调用



    调用第二次:自定义返回内容


三、其他 

  • 运行时更新速率限制

   添加IpRateLimitController控制器:   

/// <summary>
/// IP限制控制器
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class IpRateLimitController : ControllerBase
{

    private readonly IpRateLimitOptions _options;
    private readonly IIpPolicyStore _ipPolicyStore;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="optionsAccessor"></param>
    /// <param name="ipPolicyStore"></param>
    public IpRateLimitController(IOptions<IpRateLimitOptions> optionsAccessor, IIpPolicyStore ipPolicyStore)
    {
        _options = optionsAccessor.Value;
        _ipPolicyStore = ipPolicyStore;
    }

    /// <summary>
    /// 获取限制规则
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<IpRateLimitPolicies> Get()
    {
        return await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
    }

    /// <summary>
    /// 
    /// </summary>
    [HttpPost]
    public async Task Post(IpRateLimitPolicy ipRate)
    {
        var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
        if (ipRate != null)
        {
            pol.IpRules.Add(ipRate);
            await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
        }
    }
}
  • 分布式部署时,需要将速率限制计算器和ip规则存储到分布式缓存中如Redis修改注入对象
// inject counter and rules distributed cache stores
services.AddSingleton<IClientPolicyStore, DistributedCacheClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore,DistributedCacheRateLimitCounterStore>();
  • 添加Nuget包 Microsoft.Extensions.Caching.StackExchangeRedis 在Startup中设置Redis连接
services.AddStackExchangeRedisCache(options =>
{
    options.ConfigurationOptions = new ConfigurationOptions
    {
        //silently retry in the background if the Redis connection is temporarily down
        AbortOnConnectFail = false
    };
    options.Configuration = "localhost:6379";
    options.InstanceName = "AspNetRateLimit";
});
  • 限制时自定义相应结果://请求返回 "QuotaExceededResponse": { "Content": "{{\"code\":429,\"msg\":\"Visit too frequently, please try again later\",\"data\":null}}", "ContentType": "application/json;utf-8", "StatusCode": 429 },

   调用时返回结果:

相关推荐

电脑 CMD 命令大全:简单粗暴收藏版

电脑CMD命令大全包括了许多常用的命令,这些命令可以帮助用户进行各种系统管理和操作任务。以下是一些常用的CMD命令及其功能:1、系统信息和管理...

电脑维修高手必备!8个神奇DOS命令,自己动手不求人

我相信搞电脑维修或者维护的基本都会些DOS的命令。就算Windows操作系统是可视化的界面,但很多维护检查是离不开DOS命令的。掌握好这些命令,你不仅能快速诊断问题,还能解决90%的常见电脑故障。下...

一个互联网产品总监的设计技巧总结 - 技术篇

古语:工欲善其事必先利其器。往往在利其器后我们才能事半功倍。从这个角度出发成为一个合格的产品经理你需要的是“利其器”,这样你才能产品的设计过程中如鱼得水,得心应手。有些产品经理刚入职,什么都感觉自己欠...

超详解析Flutter渲染引擎|业务想创新,不了解底层原理怎么行?

作者|万红波(远湖)出品|阿里巴巴新零售淘系技术部前言Flutter作为一个跨平台的应用框架,诞生之后,就被高度关注。它通过自绘UI,解决了之前RN和weex方案难以解决的多端一致性...

瑞芯微RK3568|SDK开发之环境安装及编译操作

1.SDK简介一个通用LinuxSDK工程目录包含有buildroot、app、kernel、device、docs、external等目录。其中一些特性芯片如RK3308/RV1108/R...

且看L-MEM ECC如何守护i.MXRT1170从核CM4

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M4内核的L-MEMECC功能。本篇是《简析i.MXRT1170Cortex-M7F...

ECC给i.MXRT1170 FlexRAM带来了哪些变化?

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M7内核的FlexRAMECC功能。ECC是“ErrorCorrectingCode”...

PHP防火墙代码,防火墙,网站防火墙,WAF防火墙,PHP防火墙大全

PHP防火墙代码,防火墙,网站防火墙,WAF防火墙,PHP防火墙大全资源宝整理分享:https://www.htple.net...

从零开始移植最新版本(2023.10)主线Uboot到Orange Pi 3(全志H6)

本文将从零开始通过一步一步操作来实现将主线U-Boot最新代码移植到OrangePi3(全志H6)开发板上并正常运行起来。本文从通用移植思路的角度,展现是思考的过程,通过这种方式希望能让读者一通百...

可视化编程工具Blockly——定制工具箱

1概述本文重点讲解如何定制Blocklytoolbox上,主要包含如下几点目标:如何为toolbox不同类别添加背景色如何改变选中的类别的外观如何为toolbox类别添加定制化的css如何改变类别...

用户界面干货盘点(用户界面的基本操作方法)

DevExpressDevExpressWPF的DXSplashScreen控件在应用加载的时候显示一个启动界面。添加DXSplashScreen后,会默认生成一个XAML文件,当然,你也可...

Vue3+Bootstrap5整合:企业级后台管理系统实战

简洁而不简单,优雅而不失强大在当今快速发展的企业数字化进程中,高效、美观的后台管理系统已成为企业运营的核心支撑。作为前端开发者,我们如何选择技术栈,才能既保证开发效率,又能打造出专业级的用户体验?答案...

什么?这三款i.MXRT型号也开放了IAP API?

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT1050/1020/1015系列ROM中的FlexSPI驱动API使用。今天痞子衡去4S店给爱车做保养了,...

OneCode基础组件介绍——表格组件(Grid)

在企业级应用开发中,表格组件是数据展示与交互的核心载体。OneCode平台自研的Grid表格组件,以模型驱动设计...

开源无线LoRa传感器(光照温湿度甲醛Tvoc)

本开源项目基于ShineBlinkC2M低代码单片机实现,无需复杂单片机C语言开发。即使新手也可很容易用FlexLua零门槛开发各种功能丰富稳定可靠的IoT硬件,更多学习教程可参考Flex...

取消回复欢迎 发表评论: