并发请求太多,服务器崩溃了?试试使用 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(),就可以终止操作方法的执行了


相关文章
|
26天前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
38 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
29天前
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
42 3
|
2月前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
53 3
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
3月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
111 3
|
3月前
|
开发框架 JavaScript 前端开发
|
4月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
203 0
|
4月前
|
Rust 安全 开发者
惊爆!Xamarin 携手机器学习,开启智能应用新纪元,个性化体验与跨平台优势完美融合大揭秘!
【8月更文挑战第31天】随着互联网的发展,Web应用对性能和安全性要求不断提高。Rust凭借卓越的性能、内存安全及丰富生态,成为构建高性能Web服务器的理想选择。本文通过一个简单示例,展示如何使用Rust和Actix-web框架搭建基本Web服务器,从创建项目到运行服务器全程指导,帮助读者领略Rust在Web后端开发中的强大能力。通过实践,读者可以体验到Rust在性能和安全性方面的优势,以及其在Web开发领域的巨大潜力。
46 0
|
4月前
|
Java 数据库 API
JSF与JPA的史诗级联盟:如何编织数据持久化的华丽织锦,重塑Web应用的荣耀
【8月更文挑战第31天】JavaServer Faces (JSF) 和 Java Persistence API (JPA) 分别是构建Java Web应用的用户界面组件框架和持久化标准。结合使用JSF与JPA,能够打造强大的数据驱动Web应用。首先,通过定义实体类(如`User`)和配置`persistence.xml`来设置JPA环境。然后,在JSF中利用Managed Bean(如`UserBean`)管理业务逻辑,通过`EntityManager`执行数据持久化操作。
62 0
|
4月前
|
UED 存储 自然语言处理
【语言无界·体验无疆】解锁Vaadin应用全球化秘籍:从代码到文化,让你的应用畅游世界每一个角落!
【8月更文挑战第31天】《国际化与本地化实战:构建多语言支持的Vaadin应用》详细介绍了如何使用Vaadin框架实现应用的国际化和本地化,提升用户体验和市场竞争力。文章涵盖资源文件的创建与管理、消息绑定与动态加载、日期和数字格式化及文化敏感性处理等方面,通过具体示例代码和最佳实践,帮助开发者构建适应不同语言和地区设置的Vaadin应用。通过这些步骤,您的应用将更加灵活,满足全球用户需求。
62 0