日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

兩種基于時間窗口的限流器的簡單實現

來源: 責編: 時間:2023-11-09 09:15:02 280觀看
導讀之前開發的一款基于OpenTelemetry的Tracing組件需要使用基于速率限制(Rate Limiting)的跟蹤采樣策略,本想使用現有的解決方案,比如System.Threading.RateLimiting命名空間下的RateLimiter。大體看了RateLimiter的三種實現

之前開發的一款基于OpenTelemetry的Tracing組件需要使用基于速率限制(Rate Limiting)的跟蹤采樣策略,本想使用現有的解決方案,比如System.Threading.RateLimiting命名空間下的RateLimiter。大體看了RateLimiter的三種實現(固定窗口、滑動窗口和令牌桶),覺得過于相對復雜了點,代碼還涉及到鎖,而且提供的功能我也不太需要,于是嘗試實現一種簡單且無鎖解決方案。Aub28資訊網——每日最新資訊28at.com

一、滑動時間窗口

我為RateLimiter定義了如下這個簡單的IRateLimiter接口,唯一的無參方法TryAcquire利用返回的布爾值確定當前是否超出設定的速率限制。我只提供的兩種基于時間窗口的實現,如下所示的基于“滑動時間窗口”的實現類型SliddingWindowRateLimiter,我們在構造的時候指定時間窗口和閾值。SliddingWindowRateLimiter采用一種“討巧”的實現,它直接利用了BoundedChannel<DateTimeOffset>對象,我們將指定的閾值作為它的最大容量。Aub28資訊網——每日最新資訊28at.com

public interface IRateLimiter{    bool TryAcquire();}public sealed class SliddingWindowRateLimiter: IRateLimiter{    private readonly TimeSpan _window;    private readonly ChannelReader<DateTimeOffset> _reader;    private readonly ChannelWriter<DateTimeOffset> _writer;    public SliddingWindowRateLimiter(TimeSpan window, int permit)    {        _window = window;        var options = new BoundedChannelOptions (permit)        {            FullMode = BoundedChannelFullMode.Wait,            SingleReader = false,            SingleWriter = true        };        var channel = Channel            .CreateBounded<DateTimeOffset>(options);        _reader = channel.Reader;        _writer = channel.Writer;        Task.Factory.StartNew(            Trim,TaskCreationOptions.LongRunning);    }    public bool TryAcquire()     => _writer.TryWrite(DateTimeOffset.UtcNow);    private void Trim()    {        if (!_reader.TryPeek(out var timestamp))        {            Task.Delay(_window).Wait();            Trim();        }        else        {            var delay = _window                 - (DateTimeOffset.UtcNow - timestamp);            if (delay > TimeSpan.Zero)            {                Task.Delay(delay).Wait();                Trim();            }            else            {                var valueTask = _reader.ReadAsync();                if (!valueTask.IsCompleted)                     _ = valueTask.Result;                Trim();            }        }    }}

在實現的TryAcquire方法中,我們試著將當前時間戳寫入這個Channel,并將寫入的結果(成功或者失敗)作為返回值。為了讓Channel中只包含指定時間窗口的時間戳,我們利用一個LongRuning的Task執行Trim方法對過期的時間戳進行“裁剪”。Trim會調用ChannelReader的TRyPeek方法,如果返回False,意味著Channel為空,此時會等待一段窗口時間再進行“裁剪”。如果提取出來時間戳在Now-Window與當前時間之間,意味著Channel里面的時間戳均在設定的窗口內,此時同樣需要等待,等待時間為Window - (Now - Timestamp);只有在提取的時間超出窗口范圍,我們才需要將其從Channel中移除。Aub28資訊網——每日最新資訊28at.com

var limiter = new SliddingWindowRateLimiter(    TimeSpan.FromSeconds(2),2);var index = 0;await Task.WhenAll( Enumerable.Range(1, 100)    .Select(_ => Task.Run(() => {        while (true)        {            if (limiter.TryAcquire())            {                Console.WriteLine(                    $"[{DateTimeOffset.Now}]{Interlocked.Increment(ref index)}");            }         }    })));

我們在上面的演示程序中使用這個SliddingWindowRateLimiter,設定的限速規則為 2/2s。我們創建了100個Task并發地調用這個SliddingWindowRateLimiter,并將它返回True時的時間戳顯示出來,具體輸出如下所示。Aub28資訊網——每日最新資訊28at.com

圖片圖片Aub28資訊網——每日最新資訊28at.com

二、固定時間窗口

如下這個FixedWindowRateLimiter類型是針對“固定窗口”的實現,字段_windowTicks和_permit同樣表示時間窗口的時長(這里我們使用Int64類型的Ticks屬性)和閾值。_nextWindowStartTimeTicks表示下一次固定窗口的起始時間,這個需要動態調整,為了確保只有一個線程能夠修改它,我們定義了_windowReseting這個“信號量”。_count是一個計數器,我們使用它確定是否“超速”。Aub28資訊網——每日最新資訊28at.com

public sealed class FixedWindowRateLimiter : IRateLimiter{    private readonly long _windowTicks;    private readonly int _permit;    private long _nextWindowStartTimeTicks;    private volatile int _count = 0;    public FixedWindowRateLimiter(TimeSpan window, int permit)    {        _windowTicks = window.Ticks;        _permit = permit;        _nextWindowStartTimeTicks             = DateTimeOffset.UtcNow.Add(window).Ticks;    }    public bool TryAcquire()    {        // 超出時間窗口,重置計數器,并調整下一個時間窗口的開始時間        var now = DateTimeOffset.UtcNow.Ticks;        var nextWindowStartTimeTicks = nextWindowStartTimeTicks;        if (now >= nextWindowStartTimeTicks             && Interlocked.CompareExchange(            ref _nextWindowStartTimeTicks            , now + _windowTicks, nextWindowStartTimeTicks)             == nextWindowStartTimeTicks)        {            Interlocked.Exchange(ref _count, 1);            return true;        }        return _count < _permit             && Interlocked.Increment(ref _count) <= _permit;    }}

在實現的TryAcquire方法中,我們先確定當前時間是否超過了設定的“下一個窗口開始時間”,如果是則調用Interlocked.CompareExchange方法修改__nextWindowStartTimeTicks字段。成功修改__nextWindowStartTimeTicks的線程會調整窗口開始時間,并重置計數器_count為1,并返回True。如果計數器大于等于設定閾值,方法返回False。否則我們讓計數器+1,如果該值<=閾值,返回True,否則返回False。Aub28資訊網——每日最新資訊28at.com

IRateLimiter limiter = new FixedWindowRateLimiter(    window: TimeSpan.FromSeconds(2), permit: 2);var index = 0;await Task.WhenAll( Enumerable.Range(1, 100)    .Select(_ => Task.Run(() => {        while (true)        {            if (limiter.TryAcquire())            {                Console.WriteLine(                    $"[{DateTimeOffset.Now}]{Interlocked.Increment(ref index)}");            }               }    })));

將FixedWindowRateLimiter應用到上面的演示程序,依然能得到我們希望的輸出結果。Aub28資訊網——每日最新資訊28at.com

圖片 圖片 Aub28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-17896-0.html兩種基于時間窗口的限流器的簡單實現

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 快速入門 | 輕松掌握Hystrix實現資源隔離保護系統穩定

下一篇: IntelliJ IDEA 一些不為人知的功能

標簽:
  • 熱門焦點
  • K60 Pro官方停產 第三方瞬間漲價

    雖然沒有官方宣布,但Redmi的一些高管也已經透露了,Redmi K60 Pro已經停產且不會補貨,這一切都是為了即將到來的K60 Ultra鋪路,屬于廠家的正常操作。但有意思的是該機在停產之后
  • 盧偉冰長文解析K60至尊版 對Redmi有著里程碑式的意義

    在今天的Redmi后性能時代戰略發布會結束之后,Redmi總經理盧偉冰又帶來了一篇長文,詳解了為什么 Redmi 要開啟后性能時代?為什么選擇和 MediaTek、Pixelworks 深度合作?以及后性
  • JavaScript 混淆及反混淆代碼工具

    介紹在我們開始學習反混淆之前,我們首先要了解一下代碼混淆。如果不了解代碼是如何混淆的,我們可能無法成功對代碼進行反混淆,尤其是使用自定義混淆器對其進行混淆時。什么是混
  • Java NIO內存映射文件:提高文件讀寫效率的優秀實踐!

    Java的NIO庫提供了內存映射文件的支持,它可以將文件映射到內存中,從而可以更快地讀取和寫入文件數據。本文將對Java內存映射文件進行詳細的介紹和演示。內存映射文件概述內存
  • 騰訊蓋樓,字節拆墻

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之&ldquo;想重溫暴刷深淵、30+技能搭配暴搓到爽的游戲體驗嗎?一起上晶核,即刻暴打!&rdquo;曾憑借直播騰訊旗下代理格斗游戲《DNF》一
  • “又被陳思誠騙了”

    作者|張思齊 出品|眾面(ID:ZhongMian_ZM)如今的國產懸疑電影,成了陳思誠的天下。最近大爆電影《消失的她》票房突破30億斷層奪魁暑期檔,陳思誠再度風頭無兩。你可以說陳思誠的
  • 消費結構調整丨巨頭低價博弈,拼多多還卷得動嗎?

    來源:征探財經作者:陳香羽隨著流量紅利的退潮,電商的存量博弈越來越明顯。曾經主攻中高端與品質的淘寶天貓、京東重拾&ldquo;低價&rdquo;口號。而過去與他們錯位競爭的拼多多,靠
  • 消息稱小米汽車開始篩選交付中心:需至少120個車位

    IT之家 7 月 7 日消息,日前,有微博簡介為“汽車行業從業者、長三角一體化擁護者”的微博用戶 @長三角行健者 發文表示,據經銷商集團反饋,小米汽車目前
  • AMD的AI芯片轉單給三星可能性不大 與臺積電已合作至2nm制程

    據 DIGITIMES 消息,英偉達 AI GPU 出貨逐季飆升,接下來 AMD MI 300 系列將在第 4 季底量產。而半導體業內人士表示,近日傳出 AMD 的 AI 芯片將轉單給
Top 主站蜘蛛池模板: 奈曼旗| 汾阳市| 茶陵县| 庆元县| 康乐县| 新野县| 通辽市| 合江县| 广安市| 汤原县| 衡阳县| 安溪县| 三原县| 兴宁市| 南澳县| 峨边| 岳阳县| 连州市| 白沙| 赣州市| 通江县| 龙口市| 江孜县| 兰坪| 杭州市| 冀州市| 兴安盟| 哈尔滨市| 美姑县| 辰溪县| 鹤壁市| 四子王旗| 老河口市| 阳城县| 遂宁市| 延长县| 长宁区| 格尔木市| 沁阳市| 昌邑市| 赣榆县|