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

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

前言

请求限流(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(),就可以终止操作方法的执行了


相关文章
|
6月前
|
监控 Java 应用服务中间件
低并发编程|如何用720个请求让后端服务器瘫痪
本次故障因应用启动时未有效校验核心依赖模块初始化异常,导致后续请求处理中抛出无法捕获的错误,引发线程阻塞,最终耗尽HSF线程池,服务不可用。排查发现类初始化失败且异常未被正确处理,结合线程无限等待问题,确认为依赖初始化异常与流处理中断所致。修复措施包括加强启动校验、捕获Throwable及设置合理超时。总结指出,系统稳定性需从细节入手,防微杜渐,避免连锁故障。
低并发编程|如何用720个请求让后端服务器瘫痪
|
10月前
|
移动开发 数据挖掘 开发者
服务器发送事件(SSE)在现代Web开发中的关键作用
服务器发送事件(SSE)是HTML5标准协议,用于服务器主动向客户端推送实时数据,适合单向通信场景。相比WebSocket,SSE更简洁高效,基于HTTP协议,具备自动重连、事件驱动等特性。常见应用场景包括实时通知、新闻推送、数据分析等。通过Apipost等工具可轻松调试SSE,助力开发者构建高效实时Web应用。示例中,电商平台利用SSE实现秒杀活动通知,显著减少延迟并简化架构。掌握SSE技术,能大幅提升用户体验与开发效率。
|
9月前
|
JSON API 数据安全/隐私保护
使用curl命令在服务器上执行HTTP请求
总的来说,curl是一个非常强大的工具,它可以让你在命令行中发送各种类型的HTTP请求。通过学习和实践,你可以掌握这个工具,使你的工作更加高效。
906 30
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
316 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
JSON JavaScript 前端开发
《进阶篇第6章:vue中的ajax》包括回顾发送ajax请求方式、vue-cli脚手架配置代理服务器、vue-resource
《进阶篇第6章:vue中的ajax》包括回顾发送ajax请求方式、vue-cli脚手架配置代理服务器、vue-resource
210 22
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
329 3
|
前端开发 JavaScript Java
第6章:Vue中的ajax(包含:回顾发送ajax请求方式、vue-cli脚手架配置代理服务器)
第6章:Vue中的ajax(包含:回顾发送ajax请求方式、vue-cli脚手架配置代理服务器)
287 4
|
网络协议 Unix Linux
一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
287 4
|
监控 网络安全 调度
Quartz.Net整合NetCore3.1,部署到IIS服务器上后台定时Job不被调度的解决方案
解决Quartz.NET在.NET Core 3.1应用中部署到IIS服务器上不被调度的问题,通常需要综合考虑应用配置、IIS设置、日志分析等多个方面。采用上述策略,结合细致的测试和监控,可以有效地提高定时任务的稳定性和可靠性。在实施任何更改后,务必进行充分的测试,以验证问题是否得到解决,并监控生产环境的表现,确保长期稳定性。
1074 1
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
195 3