欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ASP.NET?Core基于滑動(dòng)窗口實(shí)現(xiàn)限流控制

 更新時(shí)間:2022年03月03日 16:14:20   作者:My?IO  
這篇文章主要介紹了ASP.NET?Core基于滑動(dòng)窗口實(shí)現(xiàn)限流控制,?AspNetCoreRateLimit是目前ASP.NET?Core下最常用的限流解決方案,下面詳細(xì)內(nèi)容,需要的小伙伴可以參考一下

前言:

在實(shí)際項(xiàng)目中,為了保障服務(wù)器的穩(wěn)定運(yùn)行,需要對(duì)接口的可訪問(wèn)頻次進(jìn)行限流控制,避免因客戶端頻繁請(qǐng)求導(dǎo)致服務(wù)器壓力過(guò)大。

而?AspNetCoreRateLimit是目前ASP.NET Core下最常用的限流解決方案。

查看它的實(shí)現(xiàn)代碼,我發(fā)現(xiàn)它使用的固定窗口算法。

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,
? ? ? ? ? ? Count = totalCount
? ? ? ? };
? ? }
}

二、固定窗口算法

固定窗口算法是將時(shí)間線劃分為固定大小的窗口,并為每個(gè)窗口分配一個(gè)計(jì)數(shù)器。每個(gè)請(qǐng)求,根據(jù)其到達(dá)時(shí)間,被映射到一個(gè)窗口。如果窗口中的計(jì)數(shù)器已達(dá)到限制,則拒絕落在此窗口中的請(qǐng)求。

例如,如果我們將窗口大小設(shè)置為one分鐘,每分鐘允許ten個(gè)請(qǐng)求:

ASP.NET Core基于滑動(dòng)窗口算法實(shí)現(xiàn)限流控制 #yyds干貨盤點(diǎn)#_滑動(dòng)窗口

59秒的請(qǐng)求將被阻止,因?yàn)檫@時(shí)已經(jīng)接受了10個(gè)請(qǐng)求。1分鐘時(shí)計(jì)數(shù)器歸零,所以1分01秒的請(qǐng)求可以接受。

??固定窗口算法的問(wèn)題主要在于,如果在窗口邊緣發(fā)生大量請(qǐng)求,會(huì)導(dǎo)致限流策略失效。??

比如,在59秒接收了9個(gè)請(qǐng)求,在1分01秒又可以再接收10個(gè)請(qǐng)求,相當(dāng)于每分鐘允許了20個(gè)請(qǐng)求。

三、滑動(dòng)窗口算法

滑動(dòng)窗口類似于固定窗口算法,但它通過(guò)將前一個(gè)窗口中的加權(quán)計(jì)數(shù)添加到當(dāng)前窗口中的計(jì)數(shù)來(lái)計(jì)算估計(jì)數(shù),如果估計(jì)數(shù)超過(guò)計(jì)數(shù)限制,則請(qǐng)求將被阻止。

具體公式如下:

估計(jì)數(shù) = 前一窗口計(jì)數(shù) * (1 - 當(dāng)前窗口經(jīng)過(guò)時(shí)間 / 單位時(shí)間) + 當(dāng)前窗口計(jì)數(shù)

例如,假設(shè)限制為每分鐘10個(gè):

窗口[00:00, 00:01)中有9個(gè)請(qǐng)求,窗口[00:01, 00:02)中有5個(gè)請(qǐng)求。對(duì)于01:15到達(dá)的請(qǐng)求,即窗口[00:01, 00:02)的25%位置,通過(guò)公式計(jì)算請(qǐng)求計(jì)數(shù):9 x (1 - 25%) + 5 = 11.75 > 10. 因此我們拒絕此請(qǐng)求。

??即使兩個(gè)窗口都沒(méi)有超過(guò)限制,請(qǐng)求也會(huì)被拒絕,因?yàn)榍耙粋€(gè)和當(dāng)前窗口的加權(quán)和確實(shí)超過(guò)了限制。??

四、實(shí)現(xiàn)

根據(jù)上面的公式,實(shí)現(xiàn)滑動(dòng)窗口算法代碼如下:

public class SlidingWindow
{
? ? private readonly object _syncObject = new object();

? ? private readonly int _requestIntervalSeconds;
? ? private readonly int _requestLimit;

? ? private DateTime _windowStartTime;
? ? private int _prevRequestCount;
? ? private int _requestCount;

? ? public SlidingWindow(int requestLimit, int requestIntervalSeconds)
? ? {
? ? ? ? _windowStartTime = DateTime.Now;
? ? ? ? _requestLimit = requestLimit;
? ? ? ? _requestIntervalSeconds = requestIntervalSeconds;
? ? }

? ? public bool PassRequest()
? ? {
? ? ? ? lock (_syncObject)
? ? ? ? {
? ? ? ? ? ? var currentTime = DateTime.Now;
? ? ? ? ? ? var elapsedSeconds = (currentTime - _windowStartTime).TotalSeconds;

? ? ? ? ? ? if (elapsedSeconds >= _requestIntervalSeconds * 2)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _windowStartTime = currentTime;
? ? ? ? ? ? ? ? _prevRequestCount = 0;
? ? ? ? ? ? ? ? _requestCount = 0;

? ? ? ? ? ? ? ? elapsedSeconds = 0;
? ? ? ? ? ? }
? ? ? ? ? ? else if (elapsedSeconds >= _requestIntervalSeconds)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _windowStartTime = _windowStartTime.AddSeconds(_requestIntervalSeconds);
? ? ? ? ? ? ? ? _prevRequestCount = _requestCount;
? ? ? ? ? ? ? ? _requestCount = 0;

? ? ? ? ? ? ? ? elapsedSeconds = (currentTime - _windowStartTime).TotalSeconds;
? ? ? ? ? ? }?

? ? ? ? ? ? var requestCount = _prevRequestCount * (1 - elapsedSeconds / _requestIntervalSeconds) + _requestCount + 1;
? ? ? ? ? ? if (requestCount <= _requestLimit)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _requestCount++;
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? return false;
? ? }
}

如果最近的2次請(qǐng)求相距2個(gè)窗口時(shí)間,則可以認(rèn)為前一窗口計(jì)數(shù)為0,重新開(kāi)始計(jì)數(shù)。

六、使用

新建Middleware,使用滑動(dòng)窗口算法進(jìn)行限流:

public class RateLimitMiddleware : IMiddleware
{
? ? private readonly SlidingWindow _window;

? ? public RateLimitMiddleware()
? ? {
? ? ? ? _window = new SlidingWindow(10, 60);
? ? }
? ? public async Task InvokeAsync(HttpContext context, RequestDelegate next)
? ? {
? ? ? ? if (!_window.PassRequest())
? ? ? ? {
? ? ? ? ? ? context.SetEndpoint(new Endpoint((context) =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? context.Response.StatusCode = StatusCodes.Status403Forbidden;
? ? ? ? ? ? ? ? return Task.CompletedTask;
? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? ? ? ? EndpointMetadataCollection.Empty,
? ? ? ? ? ? ? ? ? ? ? ? "限流"));
? ? ? ? }

? ? ? ? await next(context);
? ? }
}

??需要注意的是,我們注冊(cè)Middleware時(shí),必須使用單例模式,保證所有請(qǐng)求通過(guò)同一SlidingWindow計(jì)數(shù):??

services.AddSingleton<RateLimitMiddleware>();

結(jié)論:

使用滑動(dòng)窗口算法,可以有效避免固定窗口算法存在的窗口邊緣大量請(qǐng)求無(wú)法限制的問(wèn)題。

到此這篇關(guān)于ASP.NET Core基于滑動(dòng)窗口實(shí)現(xiàn)限流控制的文章就介紹到這了,更多相關(guān)ASP.NET Core基于滑動(dòng)窗口實(shí)現(xiàn)限流控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論