并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流

image

前言

请求限流(Rate Limiting)主要是一种用于控制客户端对服务器的请求频率的机制。

其目的是限制客户端在一定时间内可以发送的请求数量,保护服务器免受过多请求的影响,确保系统的稳定性和可靠性。

请求限流通常会基于以下几个因素来进行限制:

  1. 时间窗口:规定了在多长时间内允许的请求次数
  2. 请求配额:在时间窗口内允许的最大请求数量
  3. 客户端标识:根据客户端的 IP 地址、用户标识或其他标识符来进行限流

请求限流技术可以应用在很多场景,本文主要讲述 ASP.NET Core Web API 如何使用操作筛选器对请求进行限流。

Step By Step 步骤

  1. 创建一个ASP.NET Core Web API 项目

  2. 编写自定义的操作筛选器 RateLimitFilter,实现 “1s内只允许最多有一个来自同一个IP地址的请求”(留意注释

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Filters;
    using Microsoft.Extensions.Caching.Memory;
    
    public class RateLimitFilter : IAsyncActionFilter
    {
    	private readonly IMemoryCache memCache;
    
    	// 注入的IMemoryCache
    	public RateLimitFilter(IMemoryCache memCache)
    	{
    		this.memCache = memCache;
    	}
    
    	public Task OnActionExecutionAsync(
    		ActionExecutingContext context, 
    		ActionExecutionDelegate next)
    	{
    		// 通过注入的 IMemoryCache 来记录用户上一次访问的时间戳
    		// 在分布式系统下可以改用分布式缓存来代替内存缓存
    		string removeIP = context.HttpContext.Connection.RemoteIpAddress!.ToString();
    		string cacheKey = $"LastVisitTick_{removeIP}";
    		
    		// 从缓存中获取这个客户端IP地址上一次访问服务器的时间
    		long? lastTick = memCache.Get<long?>(cacheKey);
    		if (lastTick == null || Environment.TickCount64 - lastTick > 1000)
    		{
    			// 如果缓存中不存在上一次访问时间或者上一次访问时间距离现在已经超过 1s,则通过 next 来执行后面的筛选器
    			memCache.Set(cacheKey, Environment.TickCount64, TimeSpan.FromSeconds(10));
    			return next();
    		}
    		else
    		{
    			// 否则说明 IP 频繁访问,不执行 next,相当于终止操作方法的执行
    			context.Result = new ContentResult { StatusCode = 429 };
    			return Task.CompletedTask;
    		}
    	}
    }
    

    代码中的内存缓存和分布式缓存可以参考本人之前文章《看看 Asp.net core Webapi 项目如何优雅地使用内存缓存》和《看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存

  3. 打开 Program.cs,注册这个操作筛选器

    using Microsoft.AspNetCore.Mvc;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    // 注册内存缓存服务
    builder.Services.AddMemoryCache();
    
    // 注册请求限流过滤器
    builder.Services.Configure<MvcOptions>(options => { 
    	options.Filters.Add<RateLimitFilter>();
    });
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
    	app.UseSwagger();
    	app.UseSwaggerUI();
    }
    
    app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();
    

测试

启动项目,并且访问接口,如果访问频率不高的话,接口能够正常工作。

如果访问频率很高的话,服务器就会提示 “Only once per second!”

总结

在操作筛选器中,通过 await next() 来执行下一个筛选器,

如果没有下一个筛选器,程序就会执行目标操作方法。

如果不调用 await next(),就可以终止操作方法的执行了

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值