.NET Core 对接口进行限流

一、为什么要对接口进行限流?


在现代的分布式系统中,尤其是面向大量用户的应用程序,接口可能会面临突发的高流量请求。如果不对这些请求进行限制,可能会导致系统过载、性能下降甚至崩溃。通过对接口进行限流,可以有效地保护系统资源,确保系统的稳定性和可靠性。

二、.NET Core 中实现接口限流的方法

1. 使用中间件实现限流

- 中间件是.NET Core 中处理请求和响应的一种方式,可以在请求到达实际的控制器方法之前进行限流操作。
- 可以使用开源库如 AspNetCoreRateLimit 来实现限流功能。首先,通过 NuGet 包管理器安装 AspNetCoreRateLimit 。
2. 配置限流规则

- 在 Startup.cs 文件的 ConfigureServices 方法中添加限流服务的配置:

services.AddMemoryCache();
services.Configure<IpRateLimitOptions>(options =>
{
    options.GeneralRules = new List<RateLimitRule>
    {
        new RateLimitRule
        {
            Endpoint = "*",
            Limit = 100,
            Period = "1m"
        }
    };
});
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
 

- 上述代码配置了每分钟限制 100 个请求的规则,适用于所有接口。

3. 使用限流中间件
- 在 Startup.cs 文件的 Configure 方法中添加限流中间件:

app.UseIpRateLimiting();
 

三、示例代码

以下是一个完整的.NET Core Web API 项目示例,展示了如何使用 AspNetCoreRateLimit 进行接口限流:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using AspNetCoreRateLimit;

namespace RateLimitExample
{
    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)
        {
            services.AddMemoryCache();
            services.Configure<IpRateLimitOptions>(options =>
            {
                options.GeneralRules = new List<RateLimitRule>
                {
                    new RateLimitRule
                    {
                        Endpoint = "*",
                        Limit = 100,
                        Period = "1m"
                    }
                };
            });
            services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
            services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIpRateLimiting();

            app.UseRouting();

            app.UseAuthorization();

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

在上述示例中,当有大量请求到达接口时, AspNetCoreRateLimit 会根据配置的规则进行限流,确保系统的稳定性。

总之,在.NET Core 中对接口进行限流是保护系统的重要手段,可以通过使用中间件和开源库来轻松实现限流功能。

### 在 .NET 8 中使用 Redis 实现限流 #### 使用 `StackExchange.Redis` 进行连接管理 为了在 .NET 8 中使用 Redis 来实现限流,推荐采用 `StackExchange.Redis` 库作为客户端工具[^1]。此库提供了高效稳定的 API 接口以便于操作 Redis 数据存储。 #### 配合专用限流组件 对于更专业的场景,则建议引入专门设计用来处理限流逻辑的第三方类库——例如 `aspnetcore-redis-rate-limiting` ,它能够很好地适配最新的 .NET 版本并充分利用其特性来简化开发工作量[^3]。 #### 基础配置与中间件集成 当考虑将限流机制融入 ASP.NET Core Web 应用程序时,除了上述提到的专业解决方案外,还可以直接借助框架自带的支持完成基本设置。这通常涉及到添加必要的服务注册以及定义具体的规则集等步骤[^4]。 下面给出一段简单的 C# 示例代码展示如何创建一个基于令牌桶算法 (Token Bucket Algorithm) 的限流器: ```csharp using System; using StackExchange.Redis; public class TokenBucketRateLimiter : IDisposable { private readonly ConnectionMultiplexer _connection; private readonly IDatabase _db; public TokenBucketRateLimiter(string redisConnectionString){ _connection = ConnectionMultiplexer.Connect(redisConnectionString); _db = _connection.GetDatabase(); } /// <summary> /// 尝试消耗指定数量的令牌. /// </summary> /// <param name="key">唯一标识符.</param> /// <param name="capacity">最大容量.</param> /// <param name="fillInterval">填充间隔时间.</param> /// <param name="tokensToConsume">要消费的数量.</param> /// <returns>返回是否成功获取所需数量的令牌.</returns> public bool TryConsumeTokens(string key, int capacity, TimeSpan fillInterval, long tokensToConsume=1L){ var nowTicks = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); // 获取当前键对应的剩余时间和已有的令牌数 var existingEntry = _db.StringGet(key); double? remainingFillTimeMs = null; long availableTokens = 0L; if (!string.IsNullOrEmpty(existingEntry)){ var parts = existingEntry.Split('|'); DateTime lastRefillTimestamp = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(parts[0])); // 计算自上次补充以来经过的时间 remainingFillTimeMs = Math.Max(0D,(lastRefillTimestamp.Add(fillInterval)-DateTimeOffset.Now).TotalMilliseconds); // 更新可用令牌数目 availableTokens = Convert.ToInt64(Math.Min(capacity,long.Parse(parts[1])+(nowTicks-lastRefillTimestamp.ToUnixTimeMilliseconds())/(double)(fillInterval.TotalMilliseconds))); }else{ availableTokens = capacity; } // 判断是否有足够的令牌可供消耗 if ((availableTokens -= tokensToConsume)>=0){ string newValue = $"{nowTicks}|{availableTokens}"; _db.KeyExpire(key,fillInterval); // 设置过期时间防止内存泄漏 _db.StringSet(key,newValue); return true; } else{ return false; } } public void Dispose(){ _connection?.Dispose(); } } ``` 该示例展示了如何构建一个简易版的令牌桶限流器,并将其状态保存至 Redis 中以支持分布式环境下的协调运作。实际应用中可能还需要根据业务需求调整参数或者增加更多功能特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值