ASP.NET限流器的简单实现
一、滑动时间窗口
我为RateLimiter定义了如下这个简单的IRateLimiter接口,唯一的无参方法TryAcquire利用返回的布尔值确定当前是否超出设定的速率限制。我只提供的两种基于时间窗口的实现,如下所示的基于“滑动时间窗口”的实现类型SliddingWindowRateLimiter,我们在构造的时候指定时间窗口和阈值。SliddingWindowRateLimiter采用一种“讨巧”的实现,它直接利用了BoundedChannel<DateTimeOffset>对象,我们将指定的阈值作为它的最大容量。
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中移除。
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时的时间戳显示出来,具体输出如下所示。

二、固定时间窗口
如下这个FixedWindowRateLimiter类型是针对“固定窗口”的实现,字段_windowTicks和_permit同样表示时间窗口的时长(这里我们使用Int64类型的Ticks属性)和阈值。 _nextWindowStartTimeTicks表示下一次固定窗口的起始时间,这个需要动态调整,为了确保只有一个线程能够修改它,我们定义了_windowReseting这个“信号量”。_count是一个计数器,我们使用它确定是否“超速”。
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。
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应用到上面的演示程序,依然能得到我们希望的输出结果。

相关文章:
ASP.NET限流器的简单实现
一、滑动时间窗口 我为RateLimiter定义了如下这个简单的IRateLimiter接口,唯一的无参方法TryAcquire利用返回的布尔值确定当前是否超出设定的速率限制。我只提供的两种基于时间窗口的实现,如下所示的基于“滑动时间窗口”的实现类型SliddingWindowRateL…...
汇编语言循环左移和循环右移如何实现的,详细的比喻一下
汇编语言中的循环左移(ROL)和循环右移(ROR)是两种基本的位操作,通常用于低级编程任务,如加密、解密、数据处理等。我将使用一个详细的比喻来解释这两种操作,以使其更易于理解。 循环左移&#…...
ChromeDriver 各版本下载地址
chromedriver 115及115之后版本下载地址:https://googlechromelabs.github.io/chrome-for-testing/ chromedriver 115之前版本下载地址:http://chromedriver.storage.googleapis.com/index.html...
计算机网络之物理层
物理层 1. 物理层的基本概念 2.物理层下面的传输媒体 传输媒体可分为两类,一类是导引型传输媒体,另一类是非导引型传输媒体。 3.传输方式 3.1 串行传输和并行传输 串行传输:串行传输是指数据是一个比特依次发送的,因此在发送端…...
沉浸式航天vr科普馆VR太空主题馆展示
科普教育从小做起,现在我们的很多地方小孩子游乐体验不单单只有草坪玩耍体验,还有很多科普知识的体验馆和游玩馆。虽然现在我们还不能真实的上太空或者潜入海底,但是这些现在已经可以逼真的展示在我们面前。通过一种虚拟现实技术手段。人们带…...
AI电话机器人能否代替人工?优缺点介绍
AI电话机器人是一种基于人工智能技术的自动语音系统,它可以模拟人类的语音交互,执行客服、销售、调查等任务。随着人工智能的发展,AI电话机器人的功能越来越强大,它们在某些领域已经能够替代人工执行任务。那么,AI电话…...
Java —— 多态
目录 1. 多态的概念 2. 多态实现条件 3. 重写 重写与重载的区别 4. 向上转型和向下转型 4.1 向上转型 4.2 向下转型 5. 多态的优缺点 6. 避免在构造方法中调用重写的方法 我们从字面上看"多态"两个字, 多态就是有多种状态/形态. 比如一个人可以有多种状态, …...
UI自动化测试(弹出框,多窗口)
一、弹出框实战 1、在UI自动化测试中经常会遇到Alert弹出框的场景。Alert类是对话框的处理,主要是对alert警告框。confirm确认框,promp消息对话框。 text():获取alert的文本 dismiss ():点击取消 accept():接受 send-keys():输入 from selenium import …...
Python爬虫程序网络请求及内容解析
目录 引言 一、网络请求 1. 导入必要的库 2. 发送请求 3. 处理响应 二、内容解析 1. HTML解析 2. 查找特定元素 3. 查找多个元素 4. 使用选择器选择元素 三、应用示例:爬取网站文章并解析标题和内容 1. 发送请求并解析HTML内容 2. 查找文章元素并提取标…...
C嘎嘎模板
> 作者简介:დ旧言~,目前大二,现在学习Java,c,c,Python等 > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解什么是模板,并且能熟练运用函数模…...
数据结构和算法八股与手撕
数据结构和算法八股文 第一章 数据结构 1.1 常见结构 见http://t.csdnimg.cn/gmc3U 1.2 二叉树重点 1.2.1 各种树的定义 满二叉树:只有度为0的结点和度为2的结点,并且度为0的结点在同一层上 完全二叉树:除了最底层节点可能没填满外&…...
windiws docker 部署jar window部署docker 转载
Windows环境下从安装docker到部署前后端分离项目(springboot+vue) 一、前期准备 1.1所需工具: 1.2docker desktop 安装 二、部署springboot后端项目 2.1 部署流程 三、部署vue前端项目 3.1相关条件 3.2部署流程 四、前后端网络请求测试 一、前期准备 1.1所需工具: ①docke…...
使用git上传代码至gitee入门(1)
文章目录 一、gitee注册新建仓库 二、git的下载三、git的简单使用(push、pull)1、将本地文件推送至gitee初始化配置用户名及邮箱将本地文件提交至gitee补充 2、将远程仓库文件拉取至本地直接拉拉至其他本地文件夹 一、gitee 注册 官网:http…...
分类预测 | MATLAB实现基于Isomap降维算法与改进蜜獾算法IHBA的Adaboost-SVM集成多输入分类预测
分类预测 | MATLAB实现基于Isomap降维算法与改进蜜獾算法IHBA的Adaboost-SVM集成多输入分类预测 目录 分类预测 | MATLAB实现基于Isomap降维算法与改进蜜獾算法IHBA的Adaboost-SVM集成多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 Isomap-Adaboost-IHBA-…...
如何解决3d max渲染效果图全白这类异常问题?
通过3d max渲染效果图时,经常会出现3Dmax渲染效果图全黑或是3Dmax渲染效果图全白这类异常问题。可能遇到这类问题较多的都是新手朋友。不知如何解决。 3dmax渲染出现异常的问题,该如何高效解决呢?今天小编这里整理几项知识点,大家…...
振南技术干货集:比萨斜塔要倒了,倾斜传感器快来!(2)
注解目录 1、倾斜传感器的那些基础干货 1.1 典型应用场景 (危楼、边坡、古建筑都是对倾斜敏感的。) 1.2 倾斜传感器的原理 1.2.1 滚珠式倾斜开关 1.2.2 加速度式倾斜传感器 1)直接输出倾角 2)加速度计算倾角 3)倾角精度的提高 (如果…...
图形学 -- Geometry几何
隐式 implicit 基于给点归类,满足某些关系的点 缺点:不规则表面难以描述! algebraic surface 直接用数学公式表示:不直观! Constructive Solid Geometry(CSG) 用简单形状进行加减 distance …...
opencv中边缘检测的方法
在OpenCV中,边缘检测的方法主要有以下几种: Sobel算子: Sobel算子是边检测器,它使用33内核来检测水平边和垂直边。Sobel算子有两个,一个是检测水平边缘的,另一个是检测垂直边缘的。在OpenCV中,…...
DigitalVirt 洛杉矶 CMIN2 VPS 测评
发布于 2023-07-16 在 https://chenhaotian.top/vps/digitalvirt-us-cmin2/ 官网链接(含AFF):https://digitalvirt.com/aff.php?aff459 美国西海岸 四网回程 CMIN2 移动新线路。 晚高峰延迟 165ms 左右,不丢包,非常…...
Qt DragDrop拖动与放置
本文章从属于 Qt实验室-CSDN博客系列 拖放操作包括两个动作:拖动(drag)和放下(drop或称为放置)。 拖动允许 对于要拖出的窗口或控件,要setDragEnabled(true) 对于要拖入的窗口或控件,要setAcceptDrops(true) 下面以一个具体的用例进行说…...
FigmaCN:3分钟破解设计师的语言障碍,工作效率提升40%的秘密武器
FigmaCN:3分钟破解设计师的语言障碍,工作效率提升40%的秘密武器 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma的英文界面而烦恼吗?每次…...
从零开始将Taotoken接入静态网站实现动态AI交互
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 从零开始将Taotoken接入静态网站实现动态AI交互 1. 场景与核心思路 对于使用 Hugo、Hexo、VuePress 等工具生成的静态网站&#x…...
HAR模型调优实战:为何精心调优的线性模型能击败复杂机器学习?
1. 项目概述:当HAR模型遇上机器学习,一场关于“调优”的较量在金融计量和量化交易领域,预测明天的市场波动率,就像试图预测一场风暴的强度,充满了挑战但也至关重要。无论是为了给衍生品定价、管理投资组合风险…...
虚拟化与加密环境下勒索软件检测的IO模式识别与模型泛化实践
1. 项目概述:当勒索软件检测遇上虚拟化与加密在存储安全领域,勒索软件检测一直是个“猫鼠游戏”。传统的检测方法,尤其是那些依赖文件熵值(Entropy)突变的方案,在过去几年里确实立下了汗马功劳。其原理很直…...
GE 和 Runtime:不是上下游,是协同决策
你以为 GE 做完融合决策,交给 Runtime 执行就行了?其实它们是一个协同系统——GE 决定"融什么",Runtime 决定"怎么跑",但 GE 的融合决策必须考虑 Runtime 的调度约束,Runtime 的调度策略也必须参考…...
Unity PBR材质工作流:800个开箱即用的工业级材质球
1. 这不是“又一个免费资源包”,而是一套能直接进项目用的材质球工作流“Unity材质球资源集”这词儿听多了,点开链接——要么是30个基础金属塑料木头,要么是200个名字叫“Metal_Rough_01_v2_final_renamed”却连UV Tile都没调对的半成品。我去…...
告别TeamViewer!在Ubuntu 22.04上安装向日葵远程控制的保姆级教程(附依赖问题解决)
在Ubuntu 22.04上无缝迁移至向日葵远程控制的完整指南当TeamViewer开始频繁弹出商业使用警告或连接不稳定时,许多Linux用户开始寻找更友好的替代方案。向日葵作为国产远程控制工具的后起之秀,不仅完全免费,还针对Linux环境做了深度优化。本文…...
Keil串口调试与程序共享端口的解决方案
1. 串口调试中的端口复用问题解析 在嵌入式开发过程中,使用Keil Vision的Monitor模式进行硬件调试时,开发板上的串口资源往往会被调试器独占。这个问题困扰过不少开发者——当我们需要在调试过程中通过串口输入测试数据时,却发现串口已经被Mo…...
AI Agent在政务审批系统中的零故障部署实践(工信部试点项目全链路复盘)
更多请点击: https://codechina.net 第一章:AI Agent在政务审批系统中的零故障部署实践(工信部试点项目全链路复盘) 在工信部“智能政务基础设施升级”试点项目中,某省政务服务网完成全国首个面向全流程审批闭环的AI …...
2026技术复盘:告别“易碎”代码,实在Agent重塑企业自动化底座
在2026年的数字化转型浪潮中,企业对于“提效”的追求已从单纯的工具引入转向深度的架构治理。 曾被寄予厚望的固定规则自动化脚本,在经历了数年的规模化应用后,其弊端正集中爆发。 许多企业发现,那些耗费巨资编写的脚本࿰…...
