ASP.NET Core中间件实现限流的代码

2022-04-17 06:41:26
目录
一、限流算法1.计数器算法1.1固定窗口算法1.2滑动窗口算法2.令牌桶算法3.漏桶算法二、ASP.NETCore中间件实现限流1.中间件代码2.在管道中的使用

一、限流算法

在高并发系统中,有三把利器用来保护系统:缓存、降级和限流。

本文主要是介绍限流,限流算法主要有以下三种:

1.计数器算法

固定窗口滑动窗口

2.令牌桶算法

3.漏桶算法

1.计数器算法

1.1 固定窗口算法

计数器算法是限流算法里最简单也是最容易实现的一种算法。比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。那么我们可以这么做:在一开 始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候,counter就加1,如果counter的值大于100并且该请求与第一个 请求的间隔时间还在1分钟之内,那么说明请求数过多;如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter。

java中的具体实现如下:

public class CounterTest {    public long timeStamp = getNowTime();    public int reqCount = 0;    public final int limit = 100; // 时间窗口内最大请求数    public final long interval = 1000; // 时间窗口ms    public boolean grant() {        long now = getNowTime();        if (now < timeStamp + interval) {            // 在时间窗口内            reqCount++;            // 判断当前时间窗口内是否超过最大请求控制数            return reqCount <= limit;        } else {            timeStamp = now;            // 超时后重置            reqCount = 1;            return true;        }    }    public long getNowTime() {        return System.currentTimeMillis();    }}

.NET Core中的具体实现如下:

AspNetCoreRateLimit是目前ASP.NET Core下最常用的限流解决方案,AspNetCoreRateLimit的源码实现是固定窗口算法如下:

var entry = await _counterStore.GetAsync(counterId, cancellationToken);if (entry.HasValue){    // entry has not expired    if (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow)    {        // increment request count        var totalCount = entry.Value.Count + _config.RateIncrementer?.Invoke() ?? 1;        // deep copy        counter = new RateLimitCounter        {            Timestamp = entry.Value.Timestamp,   esponse.StatusCode = StatusCodes.Status403Forbidden;                return Task.CompletedTask;            },                        EndpointMetadataCollection.Empty,                        "限流"));        }        await next(context);    }}

2.在管道中的使用

需要注意的是,我们注册Middleware时,必须使用单例模式,保证所有请求通过同一SlidingWindow计数:

services.AddSingleton<RateLimitMiddleware>();